Merge remote-tracking branch 'refs/remotes/raysan5/develop' into develop

This commit is contained in:
victorfisac 2016-11-01 23:11:36 +01:00
commit 80f6b2f963
30 changed files with 5405 additions and 524 deletions

View File

@ -47,7 +47,7 @@ int main()
{ {
// Update // Update
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
UpdateCamera(&camera); // Update camera and player position UpdateCamera(&camera); // Update camera
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Draw // Draw

View File

@ -39,7 +39,7 @@ int main()
{ {
// Update // Update
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
UpdateCamera(&camera); // Update internal camera and our camera UpdateCamera(&camera); // Update camera
if (IsKeyDown('Z')) camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; if (IsKeyDown('Z')) camera.target = (Vector3){ 0.0f, 0.0f, 0.0f };
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------

View File

@ -22,7 +22,7 @@ int main()
// Define the camera to look into our 3d world // Define the camera to look into our 3d world
Camera camera; Camera camera;
camera.position = (Vector3){ 0.0f, 10.0f, 10.0f }; // Camera position camera.position = (Vector3){ 10.0f, 10.0f, 10.0f }; // Camera position
camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target) camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target)
camera.fovy = 45.0f; // Camera field-of-view Y camera.fovy = 45.0f; // Camera field-of-view Y
@ -34,9 +34,7 @@ int main()
bool collision = false; bool collision = false;
SetCameraMode(CAMERA_FREE); // Set a free camera mode SetCameraMode(camera, CAMERA_FREE); // Set a free camera mode
SetCameraPosition(camera.position); // Set internal camera position to match our camera position
SetCameraFovy(camera.fovy); // Set internal camera field-of-view Y
SetTargetFPS(60); // Set our game to run at 60 frames-per-second SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
@ -46,7 +44,7 @@ int main()
{ {
// Update // Update
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
UpdateCamera(&camera); // Update internal camera and our camera UpdateCamera(&camera); // Update camera
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
{ {

View File

@ -30,13 +30,15 @@ int main()
// Define the camera to look into our 3d world // Define the camera to look into our 3d world
Camera camera; Camera camera;
camera.position = (Vector3){ 5.0f, 5.0f, 5.0f }; // Camera position camera.position = (Vector3){ 5.0f, 2.0f, 5.0f }; // Camera position
camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point camera.target = (Vector3){ 0.0f, 2.0f, 0.0f }; // Camera looking at point
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target) camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target)
camera.fovy = 60.0f; // Camera field-of-view Y camera.fovy = 60.0f; // Camera field-of-view Y
Vector3 cubePosition = { 0.0f, 0.0f, 0.0f }; Vector3 cubePosition = { 0.0f, 0.0f, 0.0f };
SetCameraMode(camera, CAMERA_FIRST_PERSON); // Set first person camera mode
SetTargetFPS(90); // Set our game to run at 90 frames-per-second SetTargetFPS(90); // Set our game to run at 90 frames-per-second
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
@ -45,9 +47,10 @@ int main()
{ {
// Update // Update
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
UpdateVrTracking(); if (IsVrSimulator()) UpdateCamera(&camera); // Update camera (simulator mode)
else UpdateVrTracking(&camera); // Update camera with device tracking data
if (IsKeyPressed(KEY_SPACE)) ToggleVrMode(); if (IsKeyPressed(KEY_SPACE)) ToggleVrMode(); // Toggle VR mode
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Draw // Draw
@ -61,7 +64,7 @@ int main()
DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, RED); DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, RED);
DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, MAROON); DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, MAROON);
DrawGrid(10, 1.0f); DrawGrid(40, 1.0f);
End3dMode(); End3dMode();

View File

@ -21,16 +21,13 @@ int main()
InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d camera free"); InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d camera free");
// Define the camera to look into our 3d world // Define the camera to look into our 3d world
Camera camera = {{ 0.0f, 10.0f, 10.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f }; Camera camera = {{ 10.0f, 10.0f, 10.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f };
Vector3 cubePosition = { 0.0f, 0.0f, 0.0f }; Vector3 cubePosition = { 0.0f, 0.0f, 0.0f };
Vector2 cubeScreenPosition; Vector2 cubeScreenPosition;
SetCameraMode(CAMERA_FREE); // Set a free camera mode SetCameraMode(camera, CAMERA_FREE); // Set a free camera mode
SetCameraPosition(camera.position); // Set internal camera position to match our camera position
SetCameraTarget(camera.target); // Set internal camera target to match our camera target
SetCameraFovy(camera.fovy); // Set internal camera field-of-view Y
SetTargetFPS(60); // Set our game to run at 60 frames-per-second SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
@ -40,7 +37,7 @@ int main()
{ {
// Update // Update
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
UpdateCamera(&camera); // Update internal camera and our camera UpdateCamera(&camera); // Update camera
// Calculate cube screen space position (with a little offset to be in top) // Calculate cube screen space position (with a little offset to be in top)
cubeScreenPosition = GetWorldToScreen((Vector3){cubePosition.x, cubePosition.y + 2.5f, cubePosition.z}, camera); cubeScreenPosition = GetWorldToScreen((Vector3){cubePosition.x, cubePosition.y + 2.5f, cubePosition.z}, camera);

View File

@ -26,20 +26,17 @@ int main()
Texture2D bill = LoadTexture("resources/billboard.png"); // Our texture billboard Texture2D bill = LoadTexture("resources/billboard.png"); // Our texture billboard
Vector3 billPosition = { 0.0f, 2.0f, 0.0f }; // Position where draw billboard Vector3 billPosition = { 0.0f, 2.0f, 0.0f }; // Position where draw billboard
SetCameraMode(CAMERA_ORBITAL); // Set an orbital camera mode SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode
SetCameraPosition(camera.position); // Set internal camera position to match our camera position
SetCameraTarget(camera.target); // Set internal camera target to match our camera target
SetCameraFovy(camera.fovy); // Set internal camera field-of-view Y
SetTargetFPS(60); // Set our game to run at 60 frames-per-second SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
// Main game loop // Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key while (!WindowShouldClose()) // Detect window close button or ESC key
{ {
// Update // Update
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
UpdateCamera(&camera); // Update internal camera and our camera UpdateCamera(&camera); // Update camera
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Draw // Draw

View File

@ -45,7 +45,7 @@ int main()
{ {
// Update // Update
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
UpdateCamera(&camera); // Update internal camera and our camera UpdateCamera(&camera); // Update camera
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Draw // Draw

View File

@ -29,20 +29,19 @@ int main()
map.material.texDiffuse = texture; // Set map diffuse texture map.material.texDiffuse = texture; // Set map diffuse texture
Vector3 mapPosition = { -8.0f, 0.0f, -8.0f }; // Set model position (depends on model scaling!) Vector3 mapPosition = { -8.0f, 0.0f, -8.0f }; // Set model position (depends on model scaling!)
UnloadImage(image); // Unload heightmap image from RAM, already uploaded to VRAM UnloadImage(image); // Unload heightmap image from RAM, already uploaded to VRAM
SetCameraMode(CAMERA_ORBITAL); // Set an orbital camera mode SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode
SetCameraPosition(camera.position); // Set internal camera position to match our custom camera position
SetTargetFPS(60); // Set our game to run at 60 frames-per-second SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
// Main game loop // Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key while (!WindowShouldClose()) // Detect window close button or ESC key
{ {
// Update // Update
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
UpdateCamera(&camera); // Update internal camera and our camera UpdateCamera(&camera); // Update camera
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Draw // Draw

View File

@ -38,7 +38,6 @@ uniform Light lights[maxLights];
vec3 ComputeLightPoint(Light l, vec3 n, vec3 v, float s) vec3 ComputeLightPoint(Light l, vec3 n, vec3 v, float s)
{ {
/*
vec3 surfacePos = vec3(modelMatrix*vec4(fragPosition, 1.0)); vec3 surfacePos = vec3(modelMatrix*vec4(fragPosition, 1.0));
vec3 surfaceToLight = l.position - surfacePos; vec3 surfaceToLight = l.position - surfacePos;
@ -51,17 +50,14 @@ vec3 ComputeLightPoint(Light l, vec3 n, vec3 v, float s)
if (diff > 0.0) if (diff > 0.0)
{ {
vec3 h = normalize(-l.direction + v); vec3 h = normalize(-l.direction + v);
spec = pow(dot(n, h), 3.0 + glossiness)*s; spec = pow(abs(dot(n, h)), 3.0 + glossiness)*s;
} }
return (diff*l.diffuse.rgb + spec*colSpecular.rgb); return (diff*l.diffuse.rgb + spec*colSpecular.rgb);
*/
return vec3(0.5);
} }
vec3 ComputeLightDirectional(Light l, vec3 n, vec3 v, float s) vec3 ComputeLightDirectional(Light l, vec3 n, vec3 v, float s)
{ {
/*
vec3 lightDir = normalize(-l.direction); vec3 lightDir = normalize(-l.direction);
// Diffuse shading // Diffuse shading
@ -72,18 +68,15 @@ vec3 ComputeLightDirectional(Light l, vec3 n, vec3 v, float s)
if (diff > 0.0) if (diff > 0.0)
{ {
vec3 h = normalize(lightDir + v); vec3 h = normalize(lightDir + v);
spec = pow(dot(n, h), 3.0 + glossiness)*s; spec = pow(abs(dot(n, h)), 3.0 + glossiness)*s;
} }
// Combine results // Combine results
return (diff*l.intensity*l.diffuse.rgb + spec*colSpecular.rgb); return (diff*l.intensity*l.diffuse.rgb + spec*colSpecular.rgb);
*/
return vec3(0.5);
} }
vec3 ComputeLightSpot(Light l, vec3 n, vec3 v, float s) vec3 ComputeLightSpot(Light l, vec3 n, vec3 v, float s)
{ {
/*
vec3 surfacePos = vec3(modelMatrix*vec4(fragPosition, 1)); vec3 surfacePos = vec3(modelMatrix*vec4(fragPosition, 1));
vec3 lightToSurface = normalize(surfacePos - l.position); vec3 lightToSurface = normalize(surfacePos - l.position);
vec3 lightDir = normalize(-l.direction); vec3 lightDir = normalize(-l.direction);
@ -108,12 +101,10 @@ vec3 ComputeLightSpot(Light l, vec3 n, vec3 v, float s)
if (diffAttenuation > 0.0) if (diffAttenuation > 0.0)
{ {
vec3 h = normalize(lightDir + v); vec3 h = normalize(lightDir + v);
spec = pow(dot(n, h), 3.0 + glossiness)*s; spec = pow(abs(dot(n, h)), 3.0 + glossiness)*s;
} }
return (falloff*(diffAttenuation*l.diffuse.rgb + spec*colSpecular.rgb)); return (falloff*(diffAttenuation*l.diffuse.rgb + spec*colSpecular.rgb));
*/
return vec3(0.5);
} }
void main() void main()
@ -140,7 +131,7 @@ void main()
// Calculate specular texture color fetching or set to maximum specular value by default // Calculate specular texture color fetching or set to maximum specular value by default
float spec = 1.0; float spec = 1.0;
if (useSpecular == 1) spec *= normalize(texture2D(texture2, fragTexCoord).r); if (useSpecular == 1) spec = texture2D(texture2, fragTexCoord).r;
for (int i = 0; i < maxLights; i++) for (int i = 0; i < maxLights; i++)
{ {

View File

@ -50,7 +50,7 @@ vec3 ComputeLightPoint(Light l, vec3 n, vec3 v, float s)
if (diff > 0.0) if (diff > 0.0)
{ {
vec3 h = normalize(-l.direction + v); vec3 h = normalize(-l.direction + v);
spec = pow(dot(n, h), 3.0 + glossiness)*s; spec = pow(abs(dot(n, h)), 3.0 + glossiness)*s;
} }
return (diff*l.diffuse.rgb + spec*colSpecular.rgb); return (diff*l.diffuse.rgb + spec*colSpecular.rgb);
@ -68,7 +68,7 @@ vec3 ComputeLightDirectional(Light l, vec3 n, vec3 v, float s)
if (diff > 0.0) if (diff > 0.0)
{ {
vec3 h = normalize(lightDir + v); vec3 h = normalize(lightDir + v);
spec = pow(dot(n, h), 3.0 + glossiness)*s; spec = pow(abs(dot(n, h)), 3.0 + glossiness)*s;
} }
// Combine results // Combine results
@ -101,7 +101,7 @@ vec3 ComputeLightSpot(Light l, vec3 n, vec3 v, float s)
if (diffAttenuation > 0.0) if (diffAttenuation > 0.0)
{ {
vec3 h = normalize(lightDir + v); vec3 h = normalize(lightDir + v);
spec = pow(dot(n, h), 3.0 + glossiness)*s; spec = pow(abs(dot(n, h)), 3.0 + glossiness)*s;
} }
return (falloff*(diffAttenuation*l.diffuse.rgb + spec*colSpecular.rgb)); return (falloff*(diffAttenuation*l.diffuse.rgb + spec*colSpecular.rgb));
@ -131,7 +131,7 @@ void main()
// Calculate specular texture color fetching or set to maximum specular value by default // Calculate specular texture color fetching or set to maximum specular value by default
float spec = 1.0; float spec = 1.0;
if (useSpecular == 1) spec *= normalize(texture(texture2, fragTexCoord).r); if (useSpecular == 1) spec = texture(texture2, fragTexCoord).r;
for (int i = 0; i < maxLights; i++) for (int i = 0; i < maxLights; i++)
{ {

View File

@ -51,9 +51,7 @@ int main()
RenderTexture2D target = LoadRenderTexture(screenWidth, screenHeight); RenderTexture2D target = LoadRenderTexture(screenWidth, screenHeight);
// Setup orbital camera // Setup orbital camera
SetCameraMode(CAMERA_ORBITAL); // Set an orbital camera mode SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode
SetCameraPosition(camera.position); // Set internal camera position to match our camera position
SetCameraTarget(camera.target); // Set internal camera target to match our camera target
SetTargetFPS(60); // Set our game to run at 60 frames-per-second SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
@ -71,7 +69,7 @@ int main()
// Send new value to the shader to be used on drawing // Send new value to the shader to be used on drawing
SetShaderValue(shader, swirlCenterLoc, swirlCenter, 2); SetShaderValue(shader, swirlCenterLoc, swirlCenter, 2);
UpdateCamera(&camera); // Update internal camera and our camera UpdateCamera(&camera); // Update camera
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Draw // Draw

View File

@ -42,7 +42,7 @@ int main()
Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position
SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode SetCameraMode(camera, CAMERA_FREE); // Set an orbital camera mode
SetTargetFPS(60); // Set our game to run at 60 frames-per-second SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
@ -70,6 +70,9 @@ int main()
End3dMode(); End3dMode();
DrawText("(c) Dwarf 3D model by David Moreno", screenWidth - 200, screenHeight - 20, 10, GRAY); DrawText("(c) Dwarf 3D model by David Moreno", screenWidth - 200, screenHeight - 20, 10, GRAY);
DrawText(FormatText("Camera position: (%.2f, %.2f, %.2f)", camera.position.x, camera.position.y, camera.position.z), 600, 20, 10, BLACK);
DrawText(FormatText("Camera target: (%.2f, %.2f, %.2f)", camera.target.x, camera.target.y, camera.target.z), 600, 40, 10, GRAY);
DrawFPS(10, 10); DrawFPS(10, 10);

View File

@ -45,9 +45,7 @@ int main()
RenderTexture2D target = LoadRenderTexture(screenWidth, screenHeight); RenderTexture2D target = LoadRenderTexture(screenWidth, screenHeight);
// Setup orbital camera // Setup orbital camera
SetCameraMode(CAMERA_ORBITAL); // Set an orbital camera mode SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode
SetCameraPosition(camera.position); // Set internal camera position to match our camera position
SetCameraTarget(camera.target); // Set internal camera target to match our camera target
SetTargetFPS(60); // Set our game to run at 60 frames-per-second SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
@ -57,7 +55,7 @@ int main()
{ {
// Update // Update
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
UpdateCamera(&camera); // Update internal camera and our camera UpdateCamera(&camera); // Update camera
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Draw // Draw
@ -67,7 +65,7 @@ int main()
ClearBackground(RAYWHITE); ClearBackground(RAYWHITE);
BeginTextureMode(target); // Enable drawing to texture BeginTextureMode(target); // Enable drawing to texture
Begin3dMode(camera); Begin3dMode(camera);
DrawModel(dwarf, position, 2.0f, WHITE); // Draw 3d model with texture DrawModel(dwarf, position, 2.0f, WHITE); // Draw 3d model with texture

View File

@ -64,9 +64,7 @@ int main()
pointLight->radius = 3.0f; pointLight->radius = 3.0f;
// Setup orbital camera // Setup orbital camera
SetCameraMode(CAMERA_ORBITAL); // Set an orbital camera mode SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode
SetCameraPosition(camera.position); // Set internal camera position to match our camera position
SetCameraTarget(camera.target); // Set internal camera target to match our camera target
SetTargetFPS(60); // Set our game to run at 60 frames-per-second SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
@ -76,7 +74,7 @@ int main()
{ {
// Update // Update
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
UpdateCamera(&camera); // Update internal camera and our camera UpdateCamera(&camera); // Update camera
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Draw // Draw

View File

@ -79,6 +79,10 @@
#define JAR_MOD_IMPLEMENTATION #define JAR_MOD_IMPLEMENTATION
#include "external/jar_mod.h" // MOD loading functions #include "external/jar_mod.h" // MOD loading functions
#define DR_FLAC_IMPLEMENTATION
#define DR_FLAC_NO_WIN32_IO
#include "external/dr_flac.h" // FLAC loading functions
#ifdef _MSC_VER #ifdef _MSC_VER
#undef bool #undef bool
#endif #endif
@ -98,12 +102,13 @@
// Types and Structures Definition // Types and Structures Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
typedef enum { MUSIC_AUDIO_OGG = 0, MUSIC_MODULE_XM, MUSIC_MODULE_MOD } MusicContextType; typedef enum { MUSIC_AUDIO_OGG = 0, MUSIC_AUDIO_FLAC, MUSIC_MODULE_XM, MUSIC_MODULE_MOD } MusicContextType;
// Music type (file streaming from memory) // Music type (file streaming from memory)
typedef struct MusicData { typedef struct MusicData {
MusicContextType ctxType; // Type of music context (OGG, XM, MOD) MusicContextType ctxType; // Type of music context (OGG, XM, MOD)
stb_vorbis *ctxOgg; // OGG audio context stb_vorbis *ctxOgg; // OGG audio context
drflac *ctxFlac; // FLAC audio context
jar_xm_context_t *ctxXm; // XM chiptune context jar_xm_context_t *ctxXm; // XM chiptune context
jar_mod_context_t ctxMod; // MOD chiptune context jar_mod_context_t ctxMod; // MOD chiptune context
@ -128,6 +133,7 @@ typedef enum { INFO = 0, ERROR, WARNING, DEBUG, OTHER } TraceLogType;
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
static Wave LoadWAV(const char *fileName); // Load WAV file static Wave LoadWAV(const char *fileName); // Load WAV file
static Wave LoadOGG(const char *fileName); // Load OGG file static Wave LoadOGG(const char *fileName); // Load OGG file
static Wave LoadFLAC(const char *fileName); // Load FLAC file
#if defined(AUDIO_STANDALONE) #if defined(AUDIO_STANDALONE)
const char *GetExtension(const char *fileName); // Get the extension for a filename const char *GetExtension(const char *fileName); // Get the extension for a filename
@ -212,6 +218,7 @@ Wave LoadWave(const char *fileName)
if (strcmp(GetExtension(fileName), "wav") == 0) wave = LoadWAV(fileName); if (strcmp(GetExtension(fileName), "wav") == 0) wave = LoadWAV(fileName);
else if (strcmp(GetExtension(fileName), "ogg") == 0) wave = LoadOGG(fileName); else if (strcmp(GetExtension(fileName), "ogg") == 0) wave = LoadOGG(fileName);
else if (strcmp(GetExtension(fileName), "flac") == 0) wave = LoadFLAC(fileName);
else TraceLog(WARNING, "[%s] File extension not recognized, it can't be loaded", fileName); else TraceLog(WARNING, "[%s] File extension not recognized, it can't be loaded", fileName);
return wave; return wave;
@ -672,7 +679,7 @@ Music LoadMusicStream(const char *fileName)
// Open ogg audio stream // Open ogg audio stream
music->ctxOgg = stb_vorbis_open_filename(fileName, NULL, NULL); music->ctxOgg = stb_vorbis_open_filename(fileName, NULL, NULL);
if (music->ctxOgg == NULL) TraceLog(WARNING, "[%s] OGG audio file could not be opened", fileName); if (music->ctxOgg == NULL) TraceLog(WARNING, "[%s] OGG audio file could not be opened", fileName);
else else
{ {
stb_vorbis_info info = stb_vorbis_get_info(music->ctxOgg); // Get Ogg file info stb_vorbis_info info = stb_vorbis_get_info(music->ctxOgg); // Get Ogg file info
@ -691,6 +698,24 @@ Music LoadMusicStream(const char *fileName)
} }
} }
else if (strcmp(GetExtension(fileName), "flac") == 0)
{
music->ctxFlac = drflac_open_file(fileName);
if (music->ctxFlac == NULL) TraceLog(WARNING, "[%s] FLAC audio file could not be opened", fileName);
else
{
music->stream = InitAudioStream(music->ctxFlac->sampleRate, music->ctxFlac->bitsPerSample, music->ctxFlac->channels);
music->totalSamples = (unsigned int)music->ctxFlac->totalSampleCount;
music->samplesLeft = music->totalSamples;
music->ctxType = MUSIC_AUDIO_FLAC;
music->loop = true; // We loop by default
TraceLog(DEBUG, "[%s] FLAC sample rate: %i", fileName, music->ctxFlac->sampleRate);
TraceLog(DEBUG, "[%s] FLAC bits per sample: %i", fileName, music->ctxFlac->bitsPerSample);
TraceLog(DEBUG, "[%s] FLAC channels: %i", fileName, music->ctxFlac->channels);
}
}
else if (strcmp(GetExtension(fileName), "xm") == 0) else if (strcmp(GetExtension(fileName), "xm") == 0)
{ {
int result = jar_xm_create_context_from_file(&music->ctxXm, 48000, fileName); int result = jar_xm_create_context_from_file(&music->ctxXm, 48000, fileName);
@ -739,6 +764,7 @@ void UnloadMusicStream(Music music)
CloseAudioStream(music->stream); CloseAudioStream(music->stream);
if (music->ctxType == MUSIC_AUDIO_OGG) stb_vorbis_close(music->ctxOgg); if (music->ctxType == MUSIC_AUDIO_OGG) stb_vorbis_close(music->ctxOgg);
else if (music->ctxType == MUSIC_AUDIO_FLAC) drflac_free(music->ctxFlac);
else if (music->ctxType == MUSIC_MODULE_XM) jar_xm_free_context(music->ctxXm); else if (music->ctxType == MUSIC_MODULE_XM) jar_xm_free_context(music->ctxXm);
else if (music->ctxType == MUSIC_MODULE_MOD) jar_mod_unload(&music->ctxMod); else if (music->ctxType == MUSIC_MODULE_MOD) jar_mod_unload(&music->ctxMod);
@ -818,6 +844,20 @@ void UpdateMusicStream(Music music)
UpdateAudioStream(music->stream, pcm, numSamplesOgg*music->stream.channels); UpdateAudioStream(music->stream, pcm, numSamplesOgg*music->stream.channels);
music->samplesLeft -= (numSamplesOgg*music->stream.channels); music->samplesLeft -= (numSamplesOgg*music->stream.channels);
} break;
case MUSIC_AUDIO_FLAC:
{
if (music->samplesLeft >= AUDIO_BUFFER_SIZE) numSamples = AUDIO_BUFFER_SIZE;
else numSamples = music->samplesLeft;
int pcmi[AUDIO_BUFFER_SIZE];
// NOTE: Returns the number of samples to process (should be the same as numSamples)
unsigned int numSamplesFlac = (unsigned int)drflac_read_s32(music->ctxFlac, numSamples, pcmi);
UpdateAudioStream(music->stream, pcmi, numSamplesFlac*music->stream.channels);
music->samplesLeft -= (numSamples*music->stream.channels);
} break; } break;
case MUSIC_MODULE_XM: case MUSIC_MODULE_XM:
{ {
@ -1197,7 +1237,7 @@ static Wave LoadOGG(const char *fileName)
if (totalSeconds > 10) TraceLog(WARNING, "[%s] Ogg audio lenght is larger than 10 seconds (%f), that's a big file in memory, consider music streaming", fileName, totalSeconds); if (totalSeconds > 10) TraceLog(WARNING, "[%s] Ogg audio lenght is larger than 10 seconds (%f), that's a big file in memory, consider music streaming", fileName, totalSeconds);
int totalSamples = totalSeconds*info.sample_rate*info.channels; int totalSamples = (int)(totalSeconds*info.sample_rate*info.channels);
wave.sampleCount = totalSamples; wave.sampleCount = totalSamples;
wave.data = (short *)malloc(totalSamplesLength*sizeof(short)); wave.data = (short *)malloc(totalSamplesLength*sizeof(short));
@ -1214,6 +1254,24 @@ static Wave LoadOGG(const char *fileName)
return wave; return wave;
} }
// Load FLAC file into Wave structure
// NOTE: Using dr_flac library
static Wave LoadFLAC(const char *fileName)
{
Wave wave;
// Decode an entire FLAC file in one go
uint64_t totalSampleCount;
wave.data = drflac_open_and_decode_file_s32(fileName, &wave.channels, &wave.sampleRate, &totalSampleCount);
wave.sampleCount = (int)totalSampleCount;
wave.sampleSize = 32;
if (wave.data == NULL) TraceLog(WARNING, "[%s] FLAC data could not be loaded", fileName);
return wave;
}
// Some required functions for audio standalone module version // Some required functions for audio standalone module version
#if defined(AUDIO_STANDALONE) #if defined(AUDIO_STANDALONE)
// Get the extension for a filename // Get the extension for a filename

View File

@ -18,7 +18,11 @@
* *
* On PLATFORM_RPI, graphic device is managed by EGL and input system is coded in raw mode. * On PLATFORM_RPI, graphic device is managed by EGL and input system is coded in raw mode.
* *
* Copyright (c) 2014 Ramon Santamaria (@raysan5) * Module Configuration Flags:
*
* RL_LOAD_DEFAULT_FONT - Use external module functions to load default raylib font (module: text)
*
* Copyright (c) 2014-2016 Ramon Santamaria (@raysan5)
* *
* This software is provided "as-is", without any express or implied warranty. In no event * This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software. * will the authors be held liable for any damages arising from the use of this software.
@ -54,12 +58,12 @@
#endif #endif
#include <stdio.h> // Standard input / output lib #include <stdio.h> // Standard input / output lib
#include <stdlib.h> // Declares malloc() and free() for memory management, rand(), atexit() #include <stdlib.h> // Required for: malloc(), free(), rand(), atexit()
#include <stdint.h> // Required for typedef unsigned long long int uint64_t, used by hi-res timer #include <stdint.h> // Required for: typedef unsigned long long int uint64_t, used by hi-res timer
#include <time.h> // Useful to initialize random seed - Android/RPI hi-res timer (NOTE: Linux only!) #include <time.h> // Required for: time() - Android/RPI hi-res timer (NOTE: Linux only!)
#include <math.h> // Math related functions, tan() used to set perspective #include <math.h> // Required for: tan() [Used in Begin3dMode() to set perspective]
#include <string.h> // String function definitions, memset() #include <string.h> // Required for: strcmp()
#include <errno.h> // Macros for reporting and retrieving error conditions through error codes //#include <errno.h> // Macros for reporting and retrieving error conditions through error codes
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
//#define GLFW_INCLUDE_NONE // Disable the standard OpenGL header inclusion on GLFW3 //#define GLFW_INCLUDE_NONE // Disable the standard OpenGL header inclusion on GLFW3
@ -75,8 +79,7 @@
#endif #endif
#if defined(PLATFORM_ANDROID) #if defined(PLATFORM_ANDROID)
#include <jni.h> // Java native interface //#include <android/sensor.h> // Android sensors functions (accelerometer, gyroscope, light...)
#include <android/sensor.h> // Android sensors functions
#include <android/window.h> // Defines AWINDOW_FLAG_FULLSCREEN and others #include <android/window.h> // Defines AWINDOW_FLAG_FULLSCREEN and others
#include <android_native_app_glue.h> // Defines basic app state struct and manages activity #include <android_native_app_glue.h> // Defines basic app state struct and manages activity
@ -124,12 +127,14 @@
//#define DEFAULT_GAMEPAD_DEV "/dev/input/eventN" //#define DEFAULT_GAMEPAD_DEV "/dev/input/eventN"
#define MOUSE_SENSITIVITY 0.8f #define MOUSE_SENSITIVITY 0.8f
#define MAX_GAMEPADS 2 // Max number of gamepads supported
#define MAX_GAMEPAD_BUTTONS 11 // Max bumber of buttons supported (per gamepad)
#define MAX_GAMEPAD_AXIS 8 // Max number of axis supported (per gamepad)
#endif #endif
#define MAX_GAMEPADS 4 // Max number of gamepads supported
#define MAX_GAMEPAD_BUTTONS 32 // Max bumber of buttons supported (per gamepad)
#define MAX_GAMEPAD_AXIS 8 // Max number of axis supported (per gamepad)
#define RL_LOAD_DEFAULT_FONT // Load default font on window initialization (module: text)
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Types and Structures Definition // Types and Structures Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -152,9 +157,6 @@ static const char *internalDataPath; // Android internal data path to
static bool windowReady = false; // Used to detect display initialization static bool windowReady = false; // Used to detect display initialization
static bool appEnabled = true; // Used to detec if app is active static bool appEnabled = true; // Used to detec if app is active
static bool contextRebindRequired = false; // Used to know context rebind required static bool contextRebindRequired = false; // Used to know context rebind required
static int previousButtonState[128] = { 1 }; // Required to check if button pressed/released once
static int currentButtonState[128] = { 1 }; // Required to check if button pressed/released once
#endif #endif
#if defined(PLATFORM_RPI) #if defined(PLATFORM_RPI)
@ -168,15 +170,11 @@ static int defaultKeyboardMode; // Used to store default keyboar
// Mouse input variables // Mouse input variables
static int mouseStream = -1; // Mouse device file descriptor static int mouseStream = -1; // Mouse device file descriptor
static bool mouseReady = false; // Flag to know if mouse is ready static bool mouseReady = false; // Flag to know if mouse is ready
pthread_t mouseThreadId; // Mouse reading thread id static pthread_t mouseThreadId; // Mouse reading thread id
// Gamepad input variables // Gamepad input variables
static int gamepadStream[MAX_GAMEPADS] = { -1 }; // Gamepad device file descriptor (two gamepads supported) static int gamepadStream[MAX_GAMEPADS] = { -1 };// Gamepad device file descriptor
static bool gamepadReady[MAX_GAMEPADS] = { false }; // Flag to know if gamepad is ready (two gamepads supported) static pthread_t gamepadThreadId; // Gamepad reading thread id
pthread_t gamepadThreadId; // Gamepad reading thread id
int gamepadButtons[MAX_GAMEPADS][MAX_GAMEPAD_BUTTONS]; // Gamepad buttons state
float gamepadAxisValues[MAX_GAMEPADS][MAX_GAMEPAD_AXIS]; // Gamepad axis state
#endif #endif
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) #if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI)
@ -200,25 +198,32 @@ static Matrix downscaleView; // Matrix to downscale view (in case
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB) #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB)
static const char *windowTitle; // Window text title... static const char *windowTitle; // Window text title...
static bool cursorOnScreen = false; // Tracks if cursor is inside client area static bool cursorOnScreen = false; // Tracks if cursor is inside client area
static bool cursorHidden = false; // Track if cursor is hidden
static char previousKeyState[512] = { 0 }; // Required to check if key pressed/released once // Register mouse states
static char currentKeyState[512] = { 0 }; // Required to check if key pressed/released once static char previousMouseState[3] = { 0 }; // Registers previous mouse button state
static char currentMouseState[3] = { 0 }; // Registers current mouse button state
static int previousMouseWheelY = 0; // Registers previous mouse wheel variation
static int currentMouseWheelY = 0; // Registers current mouse wheel variation
static char previousGamepadState[32] = {0}; // Required to check if gamepad btn pressed/released once // Register gamepads states
static char currentGamepadState[32] = {0}; // Required to check if gamepad btn pressed/released once static bool gamepadReady[MAX_GAMEPADS] = { false }; // Flag to know if gamepad is ready
static float gamepadAxisState[MAX_GAMEPADS][MAX_GAMEPAD_AXIS]; // Gamepad axis state
static char previousMouseState[3] = { 0 }; // Required to check if mouse btn pressed/released once static char previousGamepadState[MAX_GAMEPADS][MAX_GAMEPAD_BUTTONS]; // Previous gamepad buttons state
static char currentMouseState[3] = { 0 }; // Required to check if mouse btn pressed/released once static char currentGamepadState[MAX_GAMEPADS][MAX_GAMEPAD_BUTTONS]; // Current gamepad buttons state
static int previousMouseWheelY = 0; // Required to track mouse wheel variation
static int currentMouseWheelY = 0; // Required to track mouse wheel variation
// Keyboard configuration
static int exitKey = KEY_ESCAPE; // Default exit key (ESC) static int exitKey = KEY_ESCAPE; // Default exit key (ESC)
static int lastKeyPressed = -1; // Register last key pressed
static bool cursorHidden; // Track if cursor is hidden
#endif #endif
// Register keyboard states
static char previousKeyState[512] = { 0 }; // Registers previous frame key state
static char currentKeyState[512] = { 0 }; // Registers current frame key state
static int lastKeyPressed = -1; // Register last key pressed
static int lastGamepadButtonPressed = -1; // Register last gamepad button pressed
static int gamepadAxisCount = 0; // Register number of available gamepad axis
static Vector2 mousePosition; // Mouse position on screen static Vector2 mousePosition; // Mouse position on screen
static Vector2 touchPosition[MAX_TOUCH_POINTS]; // Touch position on screen static Vector2 touchPosition[MAX_TOUCH_POINTS]; // Touch position on screen
@ -238,11 +243,10 @@ static bool showLogo = false; // Track if showing logo at init is
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Other Modules Functions Declaration (required by core) // Other Modules Functions Declaration (required by core)
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
#if defined(RL_LOAD_DEFAULT_FONT)
extern void LoadDefaultFont(void); // [Module: text] Loads default font on InitWindow() extern void LoadDefaultFont(void); // [Module: text] Loads default font on InitWindow()
extern void UnloadDefaultFont(void); // [Module: text] Unloads default font from GPU memory extern void UnloadDefaultFont(void); // [Module: text] Unloads default font from GPU memory
#endif
extern void ProcessGestureEvent(GestureEvent event); // [Module: gestures] Process gesture event and translate it into gestures
extern void UpdateGestures(void); // [Module: gestures] Update gestures detected (called in PollInputEvents())
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module specific Functions Declaration // Module specific Functions Declaration
@ -311,9 +315,11 @@ void InitWindow(int width, int height, const char *title)
// Init graphics device (display device and OpenGL context) // Init graphics device (display device and OpenGL context)
InitGraphicsDevice(width, height); InitGraphicsDevice(width, height);
// Load default font for convenience #if defined(RL_LOAD_DEFAULT_FONT)
// Load default font
// NOTE: External function (defined in module: text) // NOTE: External function (defined in module: text)
LoadDefaultFont(); LoadDefaultFont();
#endif
// Init hi-res timer // Init hi-res timer
InitTimer(); InitTimer();
@ -355,7 +361,7 @@ void InitWindow(int width, int height, const char *title)
#if defined(PLATFORM_ANDROID) #if defined(PLATFORM_ANDROID)
// Android activity initialization // Android activity initialization
void InitWindow(int width, int height, struct android_app *state) void InitWindow(int width, int height, void *state)
{ {
TraceLog(INFO, "Initializing raylib (v1.6.0)"); TraceLog(INFO, "Initializing raylib (v1.6.0)");
@ -364,7 +370,7 @@ void InitWindow(int width, int height, struct android_app *state)
screenWidth = width; screenWidth = width;
screenHeight = height; screenHeight = height;
app = state; app = (struct android_app *)state;
internalDataPath = app->activity->internalDataPath; internalDataPath = app->activity->internalDataPath;
// Set desired windows flags before initializing anything // Set desired windows flags before initializing anything
@ -420,7 +426,9 @@ void InitWindow(int width, int height, struct android_app *state)
// Close Window and Terminate Context // Close Window and Terminate Context
void CloseWindow(void) void CloseWindow(void)
{ {
#if defined(RL_LOAD_DEFAULT_FONT)
UnloadDefaultFont(); UnloadDefaultFont();
#endif
rlglClose(); // De-init rlgl rlglClose(); // De-init rlgl
@ -456,6 +464,9 @@ void CloseWindow(void)
// Wait for mouse and gamepad threads to finish before closing // Wait for mouse and gamepad threads to finish before closing
// NOTE: Those threads should already have finished at this point // NOTE: Those threads should already have finished at this point
// because they are controlled by windowShouldClose variable // because they are controlled by windowShouldClose variable
windowShouldClose = true; // Added to force threads to exit when the close window is called
pthread_join(mouseThreadId, NULL); pthread_join(mouseThreadId, NULL);
pthread_join(gamepadThreadId, NULL); pthread_join(gamepadThreadId, NULL);
#endif #endif
@ -516,6 +527,65 @@ int GetScreenHeight(void)
return screenHeight; return screenHeight;
} }
#if !defined(PLATFORM_ANDROID)
// Show mouse cursor
void ShowCursor()
{
#if defined(PLATFORM_DESKTOP)
#ifdef __linux
XUndefineCursor(glfwGetX11Display(), glfwGetX11Window(window));
#else
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
#endif
#endif
cursorHidden = false;
}
// Hide mouse cursor
void HideCursor()
{
#if defined(PLATFORM_DESKTOP)
#ifdef __linux
XColor Col;
const char Nil[] = {0};
Pixmap Pix = XCreateBitmapFromData(glfwGetX11Display(), glfwGetX11Window(window), Nil, 1, 1);
Cursor Cur = XCreatePixmapCursor(glfwGetX11Display(), Pix, Pix, &Col, &Col, 0, 0);
XDefineCursor(glfwGetX11Display(), glfwGetX11Window(window), Cur);
XFreeCursor(glfwGetX11Display(), Cur);
#else
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
#endif
#endif
cursorHidden = true;
}
// Check if mouse cursor is hidden
bool IsCursorHidden()
{
return cursorHidden;
}
// Enable mouse cursor
void EnableCursor()
{
#if defined(PLATFORM_DESKTOP)
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
#endif
cursorHidden = false;
}
// Disable mouse cursor
void DisableCursor()
{
#if defined(PLATFORM_DESKTOP)
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
#endif
cursorHidden = true;
}
#endif // !defined(PLATFORM_ANDROID)
// Sets Background Color // Sets Background Color
void ClearBackground(Color color) void ClearBackground(Color color)
{ {
@ -1034,7 +1104,6 @@ Matrix GetCameraMatrix(Camera camera)
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module Functions Definition - Input (Keyboard, Mouse, Gamepad) Functions // Module Functions Definition - Input (Keyboard, Mouse, Gamepad) Functions
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB)
// Detect if a key has been pressed once // Detect if a key has been pressed once
bool IsKeyPressed(int key) bool IsKeyPressed(int key)
{ {
@ -1057,7 +1126,7 @@ bool IsKeyDown(int key)
bool IsKeyReleased(int key) bool IsKeyReleased(int key)
{ {
bool released = false; bool released = false;
if ((currentKeyState[key] != previousKeyState[key]) && (currentKeyState[key] == 0)) released = true; if ((currentKeyState[key] != previousKeyState[key]) && (currentKeyState[key] == 0)) released = true;
else released = false; else released = false;
@ -1081,64 +1150,9 @@ int GetKeyPressed(void)
// NOTE: default exitKey is ESCAPE // NOTE: default exitKey is ESCAPE
void SetExitKey(int key) void SetExitKey(int key)
{ {
#if !defined(PLATFORM_ANDROID)
exitKey = key; exitKey = key;
}
// Hide mouse cursor
void HideCursor()
{
#if defined(PLATFORM_DESKTOP)
#ifdef __linux
XColor Col;
const char Nil[] = {0};
Pixmap Pix = XCreateBitmapFromData(glfwGetX11Display(), glfwGetX11Window(window), Nil, 1, 1);
Cursor Cur = XCreatePixmapCursor(glfwGetX11Display(), Pix, Pix, &Col, &Col, 0, 0);
XDefineCursor(glfwGetX11Display(), glfwGetX11Window(window), Cur);
XFreeCursor(glfwGetX11Display(), Cur);
#else
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
#endif
#endif #endif
cursorHidden = true;
}
// Show mouse cursor
void ShowCursor()
{
#if defined(PLATFORM_DESKTOP)
#ifdef __linux
XUndefineCursor(glfwGetX11Display(), glfwGetX11Window(window));
#else
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
#endif
#endif
cursorHidden = false;
}
// Disable mouse cursor
void DisableCursor()
{
#if defined(PLATFORM_DESKTOP)
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
#endif
cursorHidden = true;
}
// Enable mouse cursor
void EnableCursor()
{
#if defined(PLATFORM_DESKTOP)
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
#endif
cursorHidden = false;
}
// Check if mouse cursor is hidden
bool IsCursorHidden()
{
return cursorHidden;
} }
// NOTE: Gamepad support not implemented in emscripten GLFW3 (PLATFORM_WEB) // NOTE: Gamepad support not implemented in emscripten GLFW3 (PLATFORM_WEB)
@ -1147,33 +1161,51 @@ bool IsCursorHidden()
bool IsGamepadAvailable(int gamepad) bool IsGamepadAvailable(int gamepad)
{ {
bool result = false; bool result = false;
#if defined(PLATFORM_RPI) #if !defined(PLATFORM_ANDROID)
if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad]) result = true; if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad]) result = true;
#else
if (glfwJoystickPresent(gamepad) == 1) result = true;
#endif #endif
return result; return result;
} }
// Check gamepad name (if available)
bool IsGamepadName(int gamepad, const char *name)
{
bool result = false;
const char *gamepadName = NULL;
if (gamepadReady[gamepad]) gamepadName = GetGamepadName(gamepad);
if ((name != NULL) && (gamepadName != NULL)) result = (strcmp(name, gamepadName) == 0);
return result;
}
// Return gamepad internal name id
const char *GetGamepadName(int gamepad)
{
#if defined(PLATFORM_DESKTOP)
if (gamepadReady[gamepad]) return glfwGetJoystickName(gamepad);
else return NULL;
#else
return NULL;
#endif
}
// Return gamepad axis count
int GetGamepadAxisCount(int gamepad)
{
return gamepadAxisCount;
}
// Return axis movement vector for a gamepad // Return axis movement vector for a gamepad
float GetGamepadAxisMovement(int gamepad, int axis) float GetGamepadAxisMovement(int gamepad, int axis)
{ {
float value = 0; float value = 0;
#if defined(PLATFORM_RPI) #if !defined(PLATFORM_ANDROID)
if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad]) if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad] && (axis < MAX_GAMEPAD_AXIS)) value = gamepadAxisState[gamepad][axis];
{
if (axis < MAX_GAMEPAD_AXIS) value = gamepadAxisValues[gamepad][axis];
}
#else
const float *axes;
int axisCount = 0;
axes = glfwGetJoystickAxes(gamepad, &axisCount);
if (axis < axisCount) value = axes[axis];
#endif #endif
return value; return value;
@ -1184,14 +1216,11 @@ bool IsGamepadButtonPressed(int gamepad, int button)
{ {
bool pressed = false; bool pressed = false;
currentGamepadState[button] = IsGamepadButtonDown(gamepad, button); #if !defined(PLATFORM_ANDROID)
if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad] && (button < MAX_GAMEPAD_BUTTONS) &&
if (currentGamepadState[button] != previousGamepadState[button]) (currentGamepadState[gamepad][button] != previousGamepadState[gamepad][button]) &&
{ (currentGamepadState[gamepad][button] == 1)) pressed = true;
if (currentGamepadState[button]) pressed = true; #endif
previousGamepadState[button] = currentGamepadState[button];
}
else pressed = false;
return pressed; return pressed;
} }
@ -1201,18 +1230,9 @@ bool IsGamepadButtonDown(int gamepad, int button)
{ {
bool result = false; bool result = false;
#if defined(PLATFORM_RPI) #if !defined(PLATFORM_ANDROID)
// Get gamepad buttons information if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad] && (button < MAX_GAMEPAD_BUTTONS) &&
if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad] && (gamepadButtons[gamepad][button] == 1)) result = true; (currentGamepadState[gamepad][button] == 1)) result = true;
else result = false;
#else
const unsigned char *buttons;
int buttonsCount;
buttons = glfwGetJoystickButtons(gamepad, &buttonsCount);
if ((buttons != NULL) && (buttons[button] == GLFW_PRESS)) result = true;
else result = false;
#endif #endif
return result; return result;
@ -1222,15 +1242,12 @@ bool IsGamepadButtonDown(int gamepad, int button)
bool IsGamepadButtonReleased(int gamepad, int button) bool IsGamepadButtonReleased(int gamepad, int button)
{ {
bool released = false; bool released = false;
currentGamepadState[button] = IsGamepadButtonUp(gamepad, button); #if !defined(PLATFORM_ANDROID)
if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad] && (button < MAX_GAMEPAD_BUTTONS) &&
if (currentGamepadState[button] != previousGamepadState[button]) (currentGamepadState[gamepad][button] != previousGamepadState[gamepad][button]) &&
{ (currentGamepadState[gamepad][button] == 0)) released = true;
if (currentGamepadState[button]) released = true; #endif
previousGamepadState[button] = currentGamepadState[button];
}
else released = false;
return released; return released;
} }
@ -1240,24 +1257,19 @@ bool IsGamepadButtonUp(int gamepad, int button)
{ {
bool result = false; bool result = false;
#if defined(PLATFORM_RPI) #if !defined(PLATFORM_ANDROID)
// Get gamepad buttons information if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad] && (button < MAX_GAMEPAD_BUTTONS) &&
if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad] && (gamepadButtons[gamepad][button] == 0)) result = true; (currentGamepadState[gamepad][button] == 0)) result = true;
else result = false;
#else
const unsigned char *buttons;
int buttonsCount;
buttons = glfwGetJoystickButtons(gamepad, &buttonsCount);
if ((buttons != NULL) && (buttons[button] == GLFW_RELEASE)) result = true;
else result = false;
#endif #endif
return result; return result;
} }
#endif //defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB)
// Get the last gamepad button pressed
int GetGamepadButtonPressed(void)
{
return lastGamepadButtonPressed;
}
// Detect if a mouse button has been pressed once // Detect if a mouse button has been pressed once
bool IsMouseButtonPressed(int button) bool IsMouseButtonPressed(int button)
@ -1411,37 +1423,6 @@ Vector2 GetTouchPosition(int index)
return position; return position;
} }
#if defined(PLATFORM_ANDROID)
// Detect if a button has been pressed once
bool IsButtonPressed(int button)
{
bool pressed = false;
if ((currentButtonState[button] != previousButtonState[button]) && (currentButtonState[button] == 0)) pressed = true;
else pressed = false;
return pressed;
}
// Detect if a button is being pressed (button held down)
bool IsButtonDown(int button)
{
if (currentButtonState[button] == 0) return true;
else return false;
}
// Detect if a button has been released once
bool IsButtonReleased(int button)
{
bool released = false;
if ((currentButtonState[button] != previousButtonState[button]) && (currentButtonState[button] == 1)) released = true;
else released = false;
return released;
}
#endif
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module specific Functions Definition // Module specific Functions Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -1924,8 +1905,9 @@ static bool GetKeyStatus(int key)
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
return glfwGetKey(window, key); return glfwGetKey(window, key);
#elif defined(PLATFORM_ANDROID) #elif defined(PLATFORM_ANDROID)
// TODO: Check for virtual keyboard // NOTE: Android supports up to 260 keys
return false; if (key < 0 || key > 260) return false;
else return currentKeyState[key];
#elif defined(PLATFORM_RPI) #elif defined(PLATFORM_RPI)
// NOTE: Keys states are filled in PollInputEvents() // NOTE: Keys states are filled in PollInputEvents()
if (key < 0 || key > 511) return false; if (key < 0 || key > 511) return false;
@ -1953,6 +1935,13 @@ static void PollInputEvents(void)
// NOTE: Gestures update must be called every frame to reset gestures correctly // NOTE: Gestures update must be called every frame to reset gestures correctly
// because ProcessGestureEvent() is just called on an event, not every frame // because ProcessGestureEvent() is just called on an event, not every frame
UpdateGestures(); UpdateGestures();
// Reset last key pressed registered
lastKeyPressed = -1;
// Reset last gamepad button pressed registered
lastGamepadButtonPressed = -1;
gamepadAxisCount = 0;
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
// Mouse input polling // Mouse input polling
@ -1963,9 +1952,8 @@ static void PollInputEvents(void)
mousePosition.x = (float)mouseX; mousePosition.x = (float)mouseX;
mousePosition.y = (float)mouseY; mousePosition.y = (float)mouseY;
// Keyboard input polling (automatically managed by GLFW3 through callback) // Keyboard input polling (automatically managed by GLFW3 through callback)
lastKeyPressed = -1;
// Register previous keys states // Register previous keys states
for (int i = 0; i < 512; i++) previousKeyState[i] = currentKeyState[i]; for (int i = 0; i < 512; i++) previousKeyState[i] = currentKeyState[i];
@ -1975,13 +1963,62 @@ static void PollInputEvents(void)
previousMouseWheelY = currentMouseWheelY; previousMouseWheelY = currentMouseWheelY;
currentMouseWheelY = 0; currentMouseWheelY = 0;
// Check if gamepads are ready
// NOTE: We do it here in case of disconection
for (int i = 0; i < MAX_GAMEPADS; i++)
{
if (glfwJoystickPresent(i)) gamepadReady[i] = true;
else gamepadReady[i] = false;
}
// Register gamepads buttons events
for (int i = 0; i < MAX_GAMEPADS; i++)
{
if (gamepadReady[i]) // Check if gamepad is available
{
// Register previous gamepad states
for (int k = 0; k < MAX_GAMEPAD_BUTTONS; k++) previousGamepadState[i][k] = currentGamepadState[i][k];
// Get current gamepad state
// NOTE: There is no callback available, so we get it manually
const unsigned char *buttons;
int buttonsCount;
glfwPollEvents(); // Register keyboard/mouse events... and window events! buttons = glfwGetJoystickButtons(i, &buttonsCount);
for (int k = 0; (buttons != NULL) && (k < buttonsCount) && (buttonsCount < MAX_GAMEPAD_BUTTONS); k++)
{
if (buttons[k] == GLFW_PRESS)
{
currentGamepadState[i][k] = 1;
lastGamepadButtonPressed = k;
}
else currentGamepadState[i][k] = 0;
}
// Get current axis state
const float *axes;
int axisCount = 0;
axes = glfwGetJoystickAxes(i, &axisCount);
for (int k = 0; (axes != NULL) && (k < axisCount) && (k < MAX_GAMEPAD_AXIS); k++)
{
gamepadAxisState[i][k] = axes[k];
}
gamepadAxisCount = axisCount;
}
}
glfwPollEvents(); // Register keyboard/mouse events (callbacks)... and window events!
#endif #endif
#if defined(PLATFORM_ANDROID) #if defined(PLATFORM_ANDROID)
// Register previous keys states // Register previous keys states
for (int i = 0; i < 128; i++) previousButtonState[i] = currentButtonState[i]; // NOTE: Android supports up to 260 keys
for (int i = 0; i < 260; i++) previousKeyState[i] = currentKeyState[i];
// Poll Events (registered events) // Poll Events (registered events)
// NOTE: Activity is paused if not enabled (appEnabled) // NOTE: Activity is paused if not enabled (appEnabled)
@ -2245,9 +2282,11 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
// Init graphics device (display device and OpenGL context) // Init graphics device (display device and OpenGL context)
InitGraphicsDevice(screenWidth, screenHeight); InitGraphicsDevice(screenWidth, screenHeight);
// Load default font for convenience #if defined(RL_LOAD_DEFAULT_FONT)
// Load default font
// NOTE: External function (defined in module: text) // NOTE: External function (defined in module: text)
LoadDefaultFont(); LoadDefaultFont();
#endif
// TODO: GPU assets reload in case of lost focus (lost context) // TODO: GPU assets reload in case of lost focus (lost context)
// NOTE: This problem has been solved just unbinding and rebinding context from display // NOTE: This problem has been solved just unbinding and rebinding context from display
@ -2356,7 +2395,13 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
//int32_t AKeyEvent_getMetaState(event); //int32_t AKeyEvent_getMetaState(event);
// Save current button and its state // Save current button and its state
currentButtonState[keycode] = AKeyEvent_getAction(event); // Down = 0, Up = 1 // NOTE: Android key action is 0 for down and 1 for up
if (AKeyEvent_getAction(event) == 0)
{
currentKeyState[keycode] = 1; // Key down
lastKeyPressed = keycode;
}
else currentKeyState[keycode] = 0; // Key up
if (keycode == AKEYCODE_POWER) if (keycode == AKEYCODE_POWER)
{ {
@ -2802,7 +2847,9 @@ static void *GamepadThread(void *arg)
if (gamepadEvent.number < MAX_GAMEPAD_BUTTONS) if (gamepadEvent.number < MAX_GAMEPAD_BUTTONS)
{ {
// 1 - button pressed, 0 - button released // 1 - button pressed, 0 - button released
gamepadButtons[i][gamepadEvent.number] = (int)gamepadEvent.value; currentGamepadState[i][gamepadEvent.number] = (int)gamepadEvent.value;
if ((int)gamepadEvent.value == 1) lastGamepadButtonPressed = gamepadEvent.number;
} }
} }
else if (gamepadEvent.type == JS_EVENT_AXIS) else if (gamepadEvent.type == JS_EVENT_AXIS)
@ -2812,7 +2859,7 @@ static void *GamepadThread(void *arg)
if (gamepadEvent.number < MAX_GAMEPAD_AXIS) if (gamepadEvent.number < MAX_GAMEPAD_AXIS)
{ {
// NOTE: Scaling of gamepadEvent.value to get values between -1..1 // NOTE: Scaling of gamepadEvent.value to get values between -1..1
gamepadAxisValues[i][gamepadEvent.number] = (float)gamepadEvent.value/32768; gamepadAxisState[i][gamepadEvent.number] = (float)gamepadEvent.value/32768;
} }
} }
} }

4395
src/external/dr_flac.h vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -431,6 +431,11 @@ ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCi
#endif #endif
#endif #endif
#ifndef AL_SOFT_gain_clamp_ex
#define AL_SOFT_gain_clamp_ex 1
#define AL_GAIN_LIMIT_SOFT 0x200E
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

Binary file not shown.

View File

@ -4,7 +4,7 @@
* *
* Basic functions to draw 3d shapes and load/draw 3d models (.OBJ) * Basic functions to draw 3d shapes and load/draw 3d models (.OBJ)
* *
* Copyright (c) 2014 Ramon Santamaria (@raysan5) * Copyright (c) 2014-2016 Ramon Santamaria (@raysan5)
* *
* This software is provided "as-is", without any express or implied warranty. In no event * This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software. * will the authors be held liable for any damages arising from the use of this software.
@ -87,8 +87,8 @@ void DrawCircle3D(Vector3 center, float radius, float rotationAngle, Vector3 rot
{ {
rlColor4ub(color.r, color.g, color.b, color.a); rlColor4ub(color.r, color.g, color.b, color.a);
rlVertex3f(sin(DEG2RAD*i)*radius, cos(DEG2RAD*i)*radius, 0.0f); rlVertex3f(sinf(DEG2RAD*i)*radius, cosf(DEG2RAD*i)*radius, 0.0f);
rlVertex3f(sin(DEG2RAD*(i + 10))*radius, cos(DEG2RAD*(i + 10))*radius, 0.0f); rlVertex3f(sinf(DEG2RAD*(i + 10))*radius, cosf(DEG2RAD*(i + 10))*radius, 0.0f);
} }
rlEnd(); rlEnd();
rlPopMatrix(); rlPopMatrix();
@ -325,25 +325,25 @@ void DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color
{ {
for (int j = 0; j < slices; j++) for (int j = 0; j < slices; j++)
{ {
rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*i))*sin(DEG2RAD*(j*360/slices)), rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*i))*sinf(DEG2RAD*(j*360/slices)),
sin(DEG2RAD*(270+(180/(rings + 1))*i)), sinf(DEG2RAD*(270+(180/(rings + 1))*i)),
cos(DEG2RAD*(270+(180/(rings + 1))*i))*cos(DEG2RAD*(j*360/slices))); cosf(DEG2RAD*(270+(180/(rings + 1))*i))*cosf(DEG2RAD*(j*360/slices)));
rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sin(DEG2RAD*((j+1)*360/slices)), rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sinf(DEG2RAD*((j+1)*360/slices)),
sin(DEG2RAD*(270+(180/(rings + 1))*(i+1))), sinf(DEG2RAD*(270+(180/(rings + 1))*(i+1))),
cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cos(DEG2RAD*((j+1)*360/slices))); cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cosf(DEG2RAD*((j+1)*360/slices)));
rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sin(DEG2RAD*(j*360/slices)), rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sinf(DEG2RAD*(j*360/slices)),
sin(DEG2RAD*(270+(180/(rings + 1))*(i+1))), sinf(DEG2RAD*(270+(180/(rings + 1))*(i+1))),
cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cos(DEG2RAD*(j*360/slices))); cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cosf(DEG2RAD*(j*360/slices)));
rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*i))*sin(DEG2RAD*(j*360/slices)), rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*i))*sinf(DEG2RAD*(j*360/slices)),
sin(DEG2RAD*(270+(180/(rings + 1))*i)), sinf(DEG2RAD*(270+(180/(rings + 1))*i)),
cos(DEG2RAD*(270+(180/(rings + 1))*i))*cos(DEG2RAD*(j*360/slices))); cosf(DEG2RAD*(270+(180/(rings + 1))*i))*cosf(DEG2RAD*(j*360/slices)));
rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i)))*sin(DEG2RAD*((j+1)*360/slices)), rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*(i)))*sinf(DEG2RAD*((j+1)*360/slices)),
sin(DEG2RAD*(270+(180/(rings + 1))*(i))), sinf(DEG2RAD*(270+(180/(rings + 1))*(i))),
cos(DEG2RAD*(270+(180/(rings + 1))*(i)))*cos(DEG2RAD*((j+1)*360/slices))); cosf(DEG2RAD*(270+(180/(rings + 1))*(i)))*cosf(DEG2RAD*((j+1)*360/slices)));
rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sin(DEG2RAD*((j+1)*360/slices)), rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sinf(DEG2RAD*((j+1)*360/slices)),
sin(DEG2RAD*(270+(180/(rings + 1))*(i+1))), sinf(DEG2RAD*(270+(180/(rings + 1))*(i+1))),
cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cos(DEG2RAD*((j+1)*360/slices))); cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cosf(DEG2RAD*((j+1)*360/slices)));
} }
} }
rlEnd(); rlEnd();
@ -364,26 +364,26 @@ void DrawSphereWires(Vector3 centerPos, float radius, int rings, int slices, Col
{ {
for (int j = 0; j < slices; j++) for (int j = 0; j < slices; j++)
{ {
rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*i))*sin(DEG2RAD*(j*360/slices)), rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*i))*sinf(DEG2RAD*(j*360/slices)),
sin(DEG2RAD*(270+(180/(rings + 1))*i)), sinf(DEG2RAD*(270+(180/(rings + 1))*i)),
cos(DEG2RAD*(270+(180/(rings + 1))*i))*cos(DEG2RAD*(j*360/slices))); cosf(DEG2RAD*(270+(180/(rings + 1))*i))*cosf(DEG2RAD*(j*360/slices)));
rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sin(DEG2RAD*((j+1)*360/slices)), rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sinf(DEG2RAD*((j+1)*360/slices)),
sin(DEG2RAD*(270+(180/(rings + 1))*(i+1))), sinf(DEG2RAD*(270+(180/(rings + 1))*(i+1))),
cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cos(DEG2RAD*((j+1)*360/slices))); cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cosf(DEG2RAD*((j+1)*360/slices)));
rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sin(DEG2RAD*((j+1)*360/slices)), rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sinf(DEG2RAD*((j+1)*360/slices)),
sin(DEG2RAD*(270+(180/(rings + 1))*(i+1))), sinf(DEG2RAD*(270+(180/(rings + 1))*(i+1))),
cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cos(DEG2RAD*((j+1)*360/slices))); cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cosf(DEG2RAD*((j+1)*360/slices)));
rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sin(DEG2RAD*(j*360/slices)), rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sinf(DEG2RAD*(j*360/slices)),
sin(DEG2RAD*(270+(180/(rings + 1))*(i+1))), sinf(DEG2RAD*(270+(180/(rings + 1))*(i+1))),
cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cos(DEG2RAD*(j*360/slices))); cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cosf(DEG2RAD*(j*360/slices)));
rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sin(DEG2RAD*(j*360/slices)), rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sinf(DEG2RAD*(j*360/slices)),
sin(DEG2RAD*(270+(180/(rings + 1))*(i+1))), sinf(DEG2RAD*(270+(180/(rings + 1))*(i+1))),
cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cos(DEG2RAD*(j*360/slices))); cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cosf(DEG2RAD*(j*360/slices)));
rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*i))*sin(DEG2RAD*(j*360/slices)), rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*i))*sinf(DEG2RAD*(j*360/slices)),
sin(DEG2RAD*(270+(180/(rings + 1))*i)), sinf(DEG2RAD*(270+(180/(rings + 1))*i)),
cos(DEG2RAD*(270+(180/(rings + 1))*i))*cos(DEG2RAD*(j*360/slices))); cosf(DEG2RAD*(270+(180/(rings + 1))*i))*cosf(DEG2RAD*(j*360/slices)));
} }
} }
rlEnd(); rlEnd();
@ -407,21 +407,21 @@ void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float h
// Draw Body ------------------------------------------------------------------------------------- // Draw Body -------------------------------------------------------------------------------------
for (int i = 0; i < 360; i += 360/sides) for (int i = 0; i < 360; i += 360/sides)
{ {
rlVertex3f(sin(DEG2RAD*i)*radiusBottom, 0, cos(DEG2RAD*i)*radiusBottom); //Bottom Left rlVertex3f(sinf(DEG2RAD*i)*radiusBottom, 0, cosf(DEG2RAD*i)*radiusBottom); //Bottom Left
rlVertex3f(sin(DEG2RAD*(i+360/sides))*radiusBottom, 0, cos(DEG2RAD*(i+360/sides))*radiusBottom); //Bottom Right rlVertex3f(sinf(DEG2RAD*(i+360/sides))*radiusBottom, 0, cosf(DEG2RAD*(i+360/sides))*radiusBottom); //Bottom Right
rlVertex3f(sin(DEG2RAD*(i+360/sides))*radiusTop, height, cos(DEG2RAD*(i+360/sides))*radiusTop); //Top Right rlVertex3f(sinf(DEG2RAD*(i+360/sides))*radiusTop, height, cosf(DEG2RAD*(i+360/sides))*radiusTop); //Top Right
rlVertex3f(sin(DEG2RAD*i)*radiusTop, height, cos(DEG2RAD*i)*radiusTop); //Top Left rlVertex3f(sinf(DEG2RAD*i)*radiusTop, height, cosf(DEG2RAD*i)*radiusTop); //Top Left
rlVertex3f(sin(DEG2RAD*i)*radiusBottom, 0, cos(DEG2RAD*i)*radiusBottom); //Bottom Left rlVertex3f(sinf(DEG2RAD*i)*radiusBottom, 0, cosf(DEG2RAD*i)*radiusBottom); //Bottom Left
rlVertex3f(sin(DEG2RAD*(i+360/sides))*radiusTop, height, cos(DEG2RAD*(i+360/sides))*radiusTop); //Top Right rlVertex3f(sinf(DEG2RAD*(i+360/sides))*radiusTop, height, cosf(DEG2RAD*(i+360/sides))*radiusTop); //Top Right
} }
// Draw Cap -------------------------------------------------------------------------------------- // Draw Cap --------------------------------------------------------------------------------------
for (int i = 0; i < 360; i += 360/sides) for (int i = 0; i < 360; i += 360/sides)
{ {
rlVertex3f(0, height, 0); rlVertex3f(0, height, 0);
rlVertex3f(sin(DEG2RAD*i)*radiusTop, height, cos(DEG2RAD*i)*radiusTop); rlVertex3f(sinf(DEG2RAD*i)*radiusTop, height, cosf(DEG2RAD*i)*radiusTop);
rlVertex3f(sin(DEG2RAD*(i+360/sides))*radiusTop, height, cos(DEG2RAD*(i+360/sides))*radiusTop); rlVertex3f(sinf(DEG2RAD*(i+360/sides))*radiusTop, height, cosf(DEG2RAD*(i+360/sides))*radiusTop);
} }
} }
else else
@ -430,8 +430,8 @@ void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float h
for (int i = 0; i < 360; i += 360/sides) for (int i = 0; i < 360; i += 360/sides)
{ {
rlVertex3f(0, height, 0); rlVertex3f(0, height, 0);
rlVertex3f(sin(DEG2RAD*i)*radiusBottom, 0, cos(DEG2RAD*i)*radiusBottom); rlVertex3f(sinf(DEG2RAD*i)*radiusBottom, 0, cosf(DEG2RAD*i)*radiusBottom);
rlVertex3f(sin(DEG2RAD*(i+360/sides))*radiusBottom, 0, cos(DEG2RAD*(i+360/sides))*radiusBottom); rlVertex3f(sinf(DEG2RAD*(i+360/sides))*radiusBottom, 0, cosf(DEG2RAD*(i+360/sides))*radiusBottom);
} }
} }
@ -439,8 +439,8 @@ void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float h
for (int i = 0; i < 360; i += 360/sides) for (int i = 0; i < 360; i += 360/sides)
{ {
rlVertex3f(0, 0, 0); rlVertex3f(0, 0, 0);
rlVertex3f(sin(DEG2RAD*(i+360/sides))*radiusBottom, 0, cos(DEG2RAD*(i+360/sides))*radiusBottom); rlVertex3f(sinf(DEG2RAD*(i+360/sides))*radiusBottom, 0, cosf(DEG2RAD*(i+360/sides))*radiusBottom);
rlVertex3f(sin(DEG2RAD*i)*radiusBottom, 0, cos(DEG2RAD*i)*radiusBottom); rlVertex3f(sinf(DEG2RAD*i)*radiusBottom, 0, cosf(DEG2RAD*i)*radiusBottom);
} }
rlEnd(); rlEnd();
rlPopMatrix(); rlPopMatrix();
@ -460,17 +460,17 @@ void DrawCylinderWires(Vector3 position, float radiusTop, float radiusBottom, fl
for (int i = 0; i < 360; i += 360/sides) for (int i = 0; i < 360; i += 360/sides)
{ {
rlVertex3f(sin(DEG2RAD*i)*radiusBottom, 0, cos(DEG2RAD*i)*radiusBottom); rlVertex3f(sinf(DEG2RAD*i)*radiusBottom, 0, cosf(DEG2RAD*i)*radiusBottom);
rlVertex3f(sin(DEG2RAD*(i+360/sides))*radiusBottom, 0, cos(DEG2RAD*(i+360/sides))*radiusBottom); rlVertex3f(sinf(DEG2RAD*(i+360/sides))*radiusBottom, 0, cosf(DEG2RAD*(i+360/sides))*radiusBottom);
rlVertex3f(sin(DEG2RAD*(i+360/sides))*radiusBottom, 0, cos(DEG2RAD*(i+360/sides))*radiusBottom); rlVertex3f(sinf(DEG2RAD*(i+360/sides))*radiusBottom, 0, cosf(DEG2RAD*(i+360/sides))*radiusBottom);
rlVertex3f(sin(DEG2RAD*(i+360/sides))*radiusTop, height, cos(DEG2RAD*(i+360/sides))*radiusTop); rlVertex3f(sinf(DEG2RAD*(i+360/sides))*radiusTop, height, cosf(DEG2RAD*(i+360/sides))*radiusTop);
rlVertex3f(sin(DEG2RAD*(i+360/sides))*radiusTop, height, cos(DEG2RAD*(i+360/sides))*radiusTop); rlVertex3f(sinf(DEG2RAD*(i+360/sides))*radiusTop, height, cosf(DEG2RAD*(i+360/sides))*radiusTop);
rlVertex3f(sin(DEG2RAD*i)*radiusTop, height, cos(DEG2RAD*i)*radiusTop); rlVertex3f(sinf(DEG2RAD*i)*radiusTop, height, cosf(DEG2RAD*i)*radiusTop);
rlVertex3f(sin(DEG2RAD*i)*radiusTop, height, cos(DEG2RAD*i)*radiusTop); rlVertex3f(sinf(DEG2RAD*i)*radiusTop, height, cosf(DEG2RAD*i)*radiusTop);
rlVertex3f(sin(DEG2RAD*i)*radiusBottom, 0, cos(DEG2RAD*i)*radiusBottom); rlVertex3f(sinf(DEG2RAD*i)*radiusBottom, 0, cosf(DEG2RAD*i)*radiusBottom);
} }
rlEnd(); rlEnd();
rlPopMatrix(); rlPopMatrix();

View File

@ -77,10 +77,6 @@
#define PLATFORM_DESKTOP #define PLATFORM_DESKTOP
#endif #endif
#if defined(PLATFORM_ANDROID)
typedef struct android_app; // Define android_app struct (android_native_app_glue.h)
#endif
#if defined(_WIN32) && defined(BUILDING_DLL) #if defined(_WIN32) && defined(BUILDING_DLL)
#define RLAPI __declspec(dllexport) // We are building raylib as a Win32 DLL #define RLAPI __declspec(dllexport) // We are building raylib as a Win32 DLL
#elif defined(_WIN32) && defined(RAYLIB_DLL) #elif defined(_WIN32) && defined(RAYLIB_DLL)
@ -93,7 +89,7 @@
// Some basic Defines // Some basic Defines
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
#ifndef PI #ifndef PI
#define PI 3.14159265358979323846 #define PI 3.14159265358979323846f
#endif #endif
#define DEG2RAD (PI/180.0f) #define DEG2RAD (PI/180.0f)
@ -174,15 +170,18 @@
#define KEY_Y 89 #define KEY_Y 89
#define KEY_Z 90 #define KEY_Z 90
#if defined(PLATFORM_ANDROID)
// Android Physical Buttons
#define KEY_BACK 4
#define KEY_MENU 82
#define KEY_VOLUME_UP 24
#define KEY_VOLUME_DOWN 25
#endif
// Mouse Buttons // Mouse Buttons
#define MOUSE_LEFT_BUTTON 0 #define MOUSE_LEFT_BUTTON 0
#if defined(PLATFORM_WEB) #define MOUSE_RIGHT_BUTTON 1
#define MOUSE_RIGHT_BUTTON 2 #define MOUSE_MIDDLE_BUTTON 2
#define MOUSE_MIDDLE_BUTTON 1
#else
#define MOUSE_RIGHT_BUTTON 1
#define MOUSE_MIDDLE_BUTTON 2
#endif
// Touch points registered // Touch points registered
#define MAX_TOUCH_POINTS 2 #define MAX_TOUCH_POINTS 2
@ -190,24 +189,35 @@
// Gamepad Number // Gamepad Number
#define GAMEPAD_PLAYER1 0 #define GAMEPAD_PLAYER1 0
#define GAMEPAD_PLAYER2 1 #define GAMEPAD_PLAYER2 1
#define GAMEPAD_PLAYER3 2 // Not supported #define GAMEPAD_PLAYER3 2
#define GAMEPAD_PLAYER4 3 // Not supported #define GAMEPAD_PLAYER4 3
// Gamepad Buttons // Gamepad Buttons/Axis
// PS3 USB Controller // PS3 USB Controller Buttons
#define GAMEPAD_PS3_BUTTON_A 2 #define GAMEPAD_PS3_BUTTON_TRIANGLE 0
#define GAMEPAD_PS3_BUTTON_B 1 #define GAMEPAD_PS3_BUTTON_CIRCLE 1
#define GAMEPAD_PS3_BUTTON_X 3 #define GAMEPAD_PS3_BUTTON_CROSS 2
#define GAMEPAD_PS3_BUTTON_Y 4 #define GAMEPAD_PS3_BUTTON_SQUARE 3
#define GAMEPAD_PS3_BUTTON_R1 7
#define GAMEPAD_PS3_BUTTON_R2 5
#define GAMEPAD_PS3_BUTTON_L1 6 #define GAMEPAD_PS3_BUTTON_L1 6
#define GAMEPAD_PS3_BUTTON_L2 8 #define GAMEPAD_PS3_BUTTON_R1 7
#define GAMEPAD_PS3_BUTTON_L2 4
#define GAMEPAD_PS3_BUTTON_R2 5
#define GAMEPAD_PS3_BUTTON_START 8
#define GAMEPAD_PS3_BUTTON_SELECT 9 #define GAMEPAD_PS3_BUTTON_SELECT 9
#define GAMEPAD_PS3_BUTTON_START 10 #define GAMEPAD_PS3_BUTTON_UP 24
#define GAMEPAD_PS3_BUTTON_RIGHT 25
#define GAMEPAD_PS3_BUTTON_DOWN 26
#define GAMEPAD_PS3_BUTTON_LEFT 27
#define GAMEPAD_PS3_BUTTON_PS 12
// TODO: Add PS3 d-pad axis // PS3 USB Controller Axis
#define GAMEPAD_PS3_AXIS_LEFT_X 0
#define GAMEPAD_PS3_AXIS_LEFT_Y 1
#define GAMEPAD_PS3_AXIS_RIGHT_X 2
#define GAMEPAD_PS3_AXIS_RIGHT_Y 5
#define GAMEPAD_PS3_AXIS_L2 3 // 1.0(not pressed) --> -1.0(completely pressed)
#define GAMEPAD_PS3_AXIS_R2 4 // 1.0(not pressed) --> -1.0(completely pressed)
// Xbox360 USB Controller Buttons // Xbox360 USB Controller Buttons
#define GAMEPAD_XBOX_BUTTON_A 0 #define GAMEPAD_XBOX_BUTTON_A 0
@ -218,32 +228,31 @@
#define GAMEPAD_XBOX_BUTTON_RB 5 #define GAMEPAD_XBOX_BUTTON_RB 5
#define GAMEPAD_XBOX_BUTTON_SELECT 6 #define GAMEPAD_XBOX_BUTTON_SELECT 6
#define GAMEPAD_XBOX_BUTTON_START 7 #define GAMEPAD_XBOX_BUTTON_START 7
#define GAMEPAD_XBOX_BUTTON_UP 10
#define GAMEPAD_XBOX_BUTTON_RIGHT 11
#define GAMEPAD_XBOX_BUTTON_DOWN 12
#define GAMEPAD_XBOX_BUTTON_LEFT 13
#define GAMEPAD_XBOX_BUTTON_HOME 9
// Xbox360 USB Controller Axis
#define GAMEPAD_XBOX_AXIS_LEFT_X 0
#define GAMEPAD_XBOX_AXIS_LEFT_Y 1
#define GAMEPAD_XBOX_AXIS_RIGHT_X 2
#define GAMEPAD_XBOX_AXIS_RIGHT_Y 3
#define GAMEPAD_XBOX_AXIS_LT 4 // -1.0(not pressed) --> 1.0(completely pressed)
#define GAMEPAD_XBOX_AXIS_RT 5 // -1.0(not pressed) --> 1.0(completely pressed)
/*
// NOTE: For Raspberry Pi, axis must be reconfigured
#if defined(PLATFORM_RPI) #if defined(PLATFORM_RPI)
#define GAMEPAD_XBOX_AXIS_DPAD_X 7 #define GAMEPAD_XBOX_AXIS_LEFT_X 7
#define GAMEPAD_XBOX_AXIS_DPAD_Y 6 #define GAMEPAD_XBOX_AXIS_LEFT_Y 6
#define GAMEPAD_XBOX_AXIS_RIGHT_X 3 #define GAMEPAD_XBOX_AXIS_RIGHT_X 3
#define GAMEPAD_XBOX_AXIS_RIGHT_Y 4 #define GAMEPAD_XBOX_AXIS_RIGHT_Y 4
#define GAMEPAD_XBOX_AXIS_LT 2 #define GAMEPAD_XBOX_AXIS_LT 2
#define GAMEPAD_XBOX_AXIS_RT 5 #define GAMEPAD_XBOX_AXIS_RT 5
#else
#define GAMEPAD_XBOX_BUTTON_UP 10
#define GAMEPAD_XBOX_BUTTON_DOWN 12
#define GAMEPAD_XBOX_BUTTON_LEFT 13
#define GAMEPAD_XBOX_BUTTON_RIGHT 11
#define GAMEPAD_XBOX_AXIS_RIGHT_X 4
#define GAMEPAD_XBOX_AXIS_RIGHT_Y 3
#define GAMEPAD_XBOX_AXIS_LT_RT 2
#endif #endif
*/
#define GAMEPAD_XBOX_AXIS_LEFT_X 0
#define GAMEPAD_XBOX_AXIS_LEFT_Y 1
// Android Physic Buttons
#define ANDROID_BACK 4
#define ANDROID_MENU 82
#define ANDROID_VOLUME_UP 24
#define ANDROID_VOLUME_DOWN 25
// NOTE: MSC C++ compiler does not support compound literals (C99 feature) // NOTE: MSC C++ compiler does not support compound literals (C99 feature)
// Plain structures in C++ (without constructors) can be initialized from { } initializers. // Plain structures in C++ (without constructors) can be initialized from { } initializers.
@ -540,6 +549,21 @@ typedef enum {
COMPRESSED_ASTC_8x8_RGBA // 2 bpp COMPRESSED_ASTC_8x8_RGBA // 2 bpp
} TextureFormat; } TextureFormat;
// Texture parameters: filter mode
// NOTE 1: Filtering considers mipmaps if available in the texture
// NOTE 2: Filter is accordingly set for minification and magnification
typedef enum {
FILTER_POINT = 0, // No filter, just pixel aproximation
FILTER_BILINEAR, // Linear filtering
FILTER_TRILINEAR, // Trilinear filtering (linear with mipmaps)
FILTER_ANISOTROPIC_4X, // Anisotropic filtering 4x
FILTER_ANISOTROPIC_8X, // Anisotropic filtering 8x
FILTER_ANISOTROPIC_16X, // Anisotropic filtering 16x
} TextureFilterMode;
// Texture parameters: wrap mode
typedef enum { WRAP_REPEAT = 0, WRAP_CLAMP, WRAP_MIRROR } TextureWrapMode;
// Color blending modes (pre-defined) // Color blending modes (pre-defined)
typedef enum { BLEND_ALPHA = 0, BLEND_ADDITIVE, BLEND_MULTIPLIED } BlendMode; typedef enum { BLEND_ALPHA = 0, BLEND_ADDITIVE, BLEND_MULTIPLIED } BlendMode;
@ -594,7 +618,7 @@ extern "C" { // Prevents name mangling of functions
// Window and Graphics Device Functions (Module: core) // Window and Graphics Device Functions (Module: core)
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
#if defined(PLATFORM_ANDROID) #if defined(PLATFORM_ANDROID)
RLAPI void InitWindow(int width, int height, struct android_app *state); // Init Android Activity and OpenGL Graphics RLAPI void InitWindow(int width, int height, void *state); // Init Android Activity and OpenGL Graphics (struct android_app)
#elif defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB) #elif defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB)
RLAPI void InitWindow(int width, int height, const char *title); // Initialize Window and OpenGL Graphics RLAPI void InitWindow(int width, int height, const char *title); // Initialize Window and OpenGL Graphics
#endif #endif
@ -606,11 +630,13 @@ RLAPI void ToggleFullscreen(void); // Fullscreen
RLAPI int GetScreenWidth(void); // Get current screen width RLAPI int GetScreenWidth(void); // Get current screen width
RLAPI int GetScreenHeight(void); // Get current screen height RLAPI int GetScreenHeight(void); // Get current screen height
#if !defined(PLATFORM_ANDROID)
RLAPI void ShowCursor(void); // Shows cursor RLAPI void ShowCursor(void); // Shows cursor
RLAPI void HideCursor(void); // Hides cursor RLAPI void HideCursor(void); // Hides cursor
RLAPI bool IsCursorHidden(void); // Returns true if cursor is not visible RLAPI bool IsCursorHidden(void); // Returns true if cursor is not visible
RLAPI void EnableCursor(void); // Enables cursor RLAPI void EnableCursor(void); // Enables cursor
RLAPI void DisableCursor(void); // Disables cursor RLAPI void DisableCursor(void); // Disables cursor
#endif
RLAPI void ClearBackground(Color color); // Sets Background Color RLAPI void ClearBackground(Color color); // Sets Background Color
RLAPI void BeginDrawing(void); // Setup drawing canvas to start drawing RLAPI void BeginDrawing(void); // Setup drawing canvas to start drawing
@ -653,7 +679,6 @@ RLAPI int StorageLoadValue(int position); // Storage loa
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
// Input Handling Functions (Module: core) // Input Handling Functions (Module: core)
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB)
RLAPI bool IsKeyPressed(int key); // Detect if a key has been pressed once RLAPI bool IsKeyPressed(int key); // Detect if a key has been pressed once
RLAPI bool IsKeyDown(int key); // Detect if a key is being pressed RLAPI bool IsKeyDown(int key); // Detect if a key is being pressed
RLAPI bool IsKeyReleased(int key); // Detect if a key has been released once RLAPI bool IsKeyReleased(int key); // Detect if a key has been released once
@ -662,12 +687,15 @@ RLAPI int GetKeyPressed(void); // Get latest key
RLAPI void SetExitKey(int key); // Set a custom key to exit program (default is ESC) RLAPI void SetExitKey(int key); // Set a custom key to exit program (default is ESC)
RLAPI bool IsGamepadAvailable(int gamepad); // Detect if a gamepad is available RLAPI bool IsGamepadAvailable(int gamepad); // Detect if a gamepad is available
RLAPI float GetGamepadAxisMovement(int gamepad, int axis); // Return axis movement value for a gamepad axis RLAPI bool IsGamepadName(int gamepad, const char *name); // Check gamepad name (if available)
RLAPI const char *GetGamepadName(int gamepad); // Return gamepad internal name id
RLAPI bool IsGamepadButtonPressed(int gamepad, int button); // Detect if a gamepad button has been pressed once RLAPI bool IsGamepadButtonPressed(int gamepad, int button); // Detect if a gamepad button has been pressed once
RLAPI bool IsGamepadButtonDown(int gamepad, int button); // Detect if a gamepad button is being pressed RLAPI bool IsGamepadButtonDown(int gamepad, int button); // Detect if a gamepad button is being pressed
RLAPI bool IsGamepadButtonReleased(int gamepad, int button); // Detect if a gamepad button has been released once RLAPI bool IsGamepadButtonReleased(int gamepad, int button); // Detect if a gamepad button has been released once
RLAPI bool IsGamepadButtonUp(int gamepad, int button); // Detect if a gamepad button is NOT being pressed RLAPI bool IsGamepadButtonUp(int gamepad, int button); // Detect if a gamepad button is NOT being pressed
#endif RLAPI int GetGamepadButtonPressed(void); // Get the last gamepad button pressed
RLAPI int GetGamepadAxisCount(int gamepad); // Return gamepad axis count for a gamepad
RLAPI float GetGamepadAxisMovement(int gamepad, int axis); // Return axis movement value for a gamepad axis
RLAPI bool IsMouseButtonPressed(int button); // Detect if a mouse button has been pressed once RLAPI bool IsMouseButtonPressed(int button); // Detect if a mouse button has been pressed once
RLAPI bool IsMouseButtonDown(int button); // Detect if a mouse button is being pressed RLAPI bool IsMouseButtonDown(int button); // Detect if a mouse button is being pressed
@ -683,12 +711,6 @@ RLAPI int GetTouchX(void); // Returns touch p
RLAPI int GetTouchY(void); // Returns touch position Y for touch point 0 (relative to screen size) RLAPI int GetTouchY(void); // Returns touch position Y for touch point 0 (relative to screen size)
RLAPI Vector2 GetTouchPosition(int index); // Returns touch position XY for a touch point index (relative to screen size) RLAPI Vector2 GetTouchPosition(int index); // Returns touch position XY for a touch point index (relative to screen size)
#if defined(PLATFORM_ANDROID)
bool IsButtonPressed(int button); // Detect if an android physic button has been pressed
bool IsButtonDown(int button); // Detect if an android physic button is being pressed
bool IsButtonReleased(int button); // Detect if an android physic button has been released
#endif
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
// Gestures and Touch Handling Functions (Module: gestures) // Gestures and Touch Handling Functions (Module: gestures)
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
@ -762,6 +784,7 @@ RLAPI void UnloadTexture(Texture2D texture);
RLAPI void UnloadRenderTexture(RenderTexture2D target); // Unload render texture from GPU memory RLAPI void UnloadRenderTexture(RenderTexture2D target); // Unload render texture from GPU memory
RLAPI Color *GetImageData(Image image); // Get pixel data from image as a Color struct array RLAPI Color *GetImageData(Image image); // Get pixel data from image as a Color struct array
RLAPI Image GetTextureData(Texture2D texture); // Get pixel data from GPU texture and return an Image RLAPI Image GetTextureData(Texture2D texture); // Get pixel data from GPU texture and return an Image
RLAPI void UpdateTexture(Texture2D texture, void *pixels); // Update GPU texture with new data
RLAPI void ImageToPOT(Image *image, Color fillColor); // Convert image to POT (power-of-two) RLAPI void ImageToPOT(Image *image, Color fillColor); // Convert image to POT (power-of-two)
RLAPI void ImageFormat(Image *image, int newFormat); // Convert image data to desired format RLAPI void ImageFormat(Image *image, int newFormat); // Convert image data to desired format
RLAPI void ImageAlphaMask(Image *image, Image alphaMask); // Apply alpha mask to image RLAPI void ImageAlphaMask(Image *image, Image alphaMask); // Apply alpha mask to image
@ -783,7 +806,8 @@ RLAPI void ImageColorGrayscale(Image *image);
RLAPI void ImageColorContrast(Image *image, float contrast); // Modify image color: contrast (-100 to 100) RLAPI void ImageColorContrast(Image *image, float contrast); // Modify image color: contrast (-100 to 100)
RLAPI void ImageColorBrightness(Image *image, int brightness); // Modify image color: brightness (-255 to 255) RLAPI void ImageColorBrightness(Image *image, int brightness); // Modify image color: brightness (-255 to 255)
RLAPI void GenTextureMipmaps(Texture2D texture); // Generate GPU mipmaps for a texture RLAPI void GenTextureMipmaps(Texture2D texture); // Generate GPU mipmaps for a texture
RLAPI void UpdateTexture(Texture2D texture, void *pixels); // Update GPU texture with new data RLAPI void SetTextureFilter(Texture2D texture, int filterMode); // Set texture scaling filter mode
RLAPI void SetTextureWrap(Texture2D texture, int wrapMode); // Set texture wrapping mode
RLAPI void DrawTexture(Texture2D texture, int posX, int posY, Color tint); // Draw a Texture2D RLAPI void DrawTexture(Texture2D texture, int posX, int posY, Color tint); // Draw a Texture2D
RLAPI void DrawTextureV(Texture2D texture, Vector2 position, Color tint); // Draw a Texture2D with position defined as Vector2 RLAPI void DrawTextureV(Texture2D texture, Vector2 position, Color tint); // Draw a Texture2D with position defined as Vector2
@ -797,6 +821,7 @@ RLAPI void DrawTexturePro(Texture2D texture, Rectangle sourceRec, Rectangle dest
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
RLAPI SpriteFont GetDefaultFont(void); // Get the default SpriteFont RLAPI SpriteFont GetDefaultFont(void); // Get the default SpriteFont
RLAPI SpriteFont LoadSpriteFont(const char *fileName); // Load a SpriteFont image into GPU memory RLAPI SpriteFont LoadSpriteFont(const char *fileName); // Load a SpriteFont image into GPU memory
RLAPI SpriteFont LoadSpriteFontTTF(const char *fileName, int fontSize, int numChars, int *fontChars); // Load a SpriteFont from TTF font with parameters
RLAPI void UnloadSpriteFont(SpriteFont spriteFont); // Unload SpriteFont from GPU memory RLAPI void UnloadSpriteFont(SpriteFont spriteFont); // Unload SpriteFont from GPU memory
RLAPI void DrawText(const char *text, int posX, int posY, int fontSize, Color color); // Draw text (using default font) RLAPI void DrawText(const char *text, int posX, int posY, int fontSize, Color color); // Draw text (using default font)
@ -896,7 +921,8 @@ RLAPI void DestroyLight(Light light); // Des
RLAPI void InitVrDevice(int vdDevice); // Init VR device RLAPI void InitVrDevice(int vdDevice); // Init VR device
RLAPI void CloseVrDevice(void); // Close VR device RLAPI void CloseVrDevice(void); // Close VR device
RLAPI bool IsVrDeviceReady(void); // Detect if VR device (or simulator) is ready RLAPI bool IsVrDeviceReady(void); // Detect if VR device (or simulator) is ready
RLAPI void UpdateVrTracking(void); // Update VR tracking (position and orientation) RLAPI bool IsVrSimulator(void); // Detect if VR simulator is running
RLAPI void UpdateVrTracking(Camera *camera); // Update VR tracking (position and orientation) and camera
RLAPI void ToggleVrMode(void); // Enable/Disable VR experience (device or simulator) RLAPI void ToggleVrMode(void); // Enable/Disable VR experience (device or simulator)
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
@ -912,7 +938,7 @@ RLAPI Sound LoadSound(const char *fileName); // Load so
RLAPI Sound LoadSoundFromWave(Wave wave); // Load sound to memory from wave data RLAPI Sound LoadSoundFromWave(Wave wave); // Load sound to memory from wave data
RLAPI Sound LoadSoundFromRES(const char *rresName, int resId); // Load sound to memory from rRES file (raylib Resource) RLAPI Sound LoadSoundFromRES(const char *rresName, int resId); // Load sound to memory from rRES file (raylib Resource)
RLAPI void UpdateSound(Sound sound, void *data, int numSamples); // Update sound buffer with new data RLAPI void UpdateSound(Sound sound, void *data, int numSamples); // Update sound buffer with new data
RLAPI void UnloadWave(Wave wave); RLAPI void UnloadWave(Wave wave); // Unload wave data
RLAPI void UnloadSound(Sound sound); // Unload sound RLAPI void UnloadSound(Sound sound); // Unload sound
RLAPI void PlaySound(Sound sound); // Play a sound RLAPI void PlaySound(Sound sound); // Play a sound
RLAPI void PauseSound(Sound sound); // Pause a sound RLAPI void PauseSound(Sound sound); // Pause a sound

View File

@ -35,7 +35,7 @@
#include <math.h> // Required for: atan2() #include <math.h> // Required for: atan2()
#ifndef RLGL_STANDALONE #ifndef RLGL_STANDALONE
#include "raymath.h" // Required for Vector3 and Matrix functions #include "raymath.h" // Required for: Vector3 and Matrix functions
#endif #endif
#if defined(GRAPHICS_API_OPENGL_11) #if defined(GRAPHICS_API_OPENGL_11)
@ -140,6 +140,14 @@
#define GL_COMPRESSED_RGBA_ASTC_8x8_KHR 0x93b7 #define GL_COMPRESSED_RGBA_ASTC_8x8_KHR 0x93b7
#endif #endif
#ifndef GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT
#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
#endif
#ifndef GL_TEXTURE_MAX_ANISOTROPY_EXT
#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
#endif
#if defined(GRAPHICS_API_OPENGL_11) #if defined(GRAPHICS_API_OPENGL_11)
#define GL_UNSIGNED_SHORT_5_6_5 0x8363 #define GL_UNSIGNED_SHORT_5_6_5 0x8363
#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 #define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
@ -283,14 +291,21 @@ static Shader standardShader; // Shader with support for lighting
static Shader currentShader; // Shader to be used on rendering (by default, defaultShader) static Shader currentShader; // Shader to be used on rendering (by default, defaultShader)
static bool standardShaderLoaded = false; // Flag to track if standard shader has been loaded static bool standardShaderLoaded = false; // Flag to track if standard shader has been loaded
// Flags for supported extensions // Extension supported flag: VAO
static bool vaoSupported = false; // VAO support (OpenGL ES2 could not support VAO extension) static bool vaoSupported = false; // VAO support (OpenGL ES2 could not support VAO extension)
// Compressed textures support flags // Extension supported flag: Compressed textures
static bool texCompETC1Supported = false; // ETC1 texture compression support static bool texCompETC1Supported = false; // ETC1 texture compression support
static bool texCompETC2Supported = false; // ETC2/EAC texture compression support static bool texCompETC2Supported = false; // ETC2/EAC texture compression support
static bool texCompPVRTSupported = false; // PVR texture compression support static bool texCompPVRTSupported = false; // PVR texture compression support
static bool texCompASTCSupported = false; // ASTC texture compression support static bool texCompASTCSupported = false; // ASTC texture compression support
// Extension supported flag: Anisotropic filtering
static bool texAnisotropicFilterSupported = false; // Anisotropic texture filtering support
static float maxAnisotropicLevel = 0.0f; // Maximum anisotropy level supported (minimum is 2.0f)
// Extension supported flag: Clamp mirror wrap mode
static bool texClampMirrorSupported = false; // Clamp mirror wrap mode supported
#endif #endif
#if defined(RLGL_OCULUS_SUPPORT) #if defined(RLGL_OCULUS_SUPPORT)
@ -372,11 +387,11 @@ static char *ReadTextFile(const char *fileName); // Read chars array from
#if defined(RLGL_OCULUS_SUPPORT) #if defined(RLGL_OCULUS_SUPPORT)
#if !defined(RLGL_STANDALONE) #if !defined(RLGL_STANDALONE)
static bool InitOculusDevice(void); // Initialize Oculus device (returns true if success) static bool InitOculusDevice(void); // Initialize Oculus device (returns true if success)
static void CloseOculusDevice(void); // Close Oculus device static void CloseOculusDevice(void); // Close Oculus device
static void UpdateOculusTracking(void); // Update Oculus head position-orientation tracking static void UpdateOculusTracking(Camera *camera); // Update Oculus head position-orientation tracking
static void BeginOculusDrawing(void); // Setup Oculus buffers for drawing static void BeginOculusDrawing(void); // Setup Oculus buffers for drawing
static void EndOculusDrawing(void); // Finish Oculus drawing and blit framebuffer to mirror static void EndOculusDrawing(void); // Finish Oculus drawing and blit framebuffer to mirror
#endif #endif
static OculusBuffer LoadOculusBuffer(ovrSession session, int width, int height); // Load Oculus required buffers static OculusBuffer LoadOculusBuffer(ovrSession session, int width, int height); // Load Oculus required buffers
@ -871,6 +886,37 @@ void rlDisableTexture(void)
#endif #endif
} }
// Set texture parameters (wrap mode/filter mode)
void rlTextureParameters(unsigned int id, int param, int value)
{
glBindTexture(GL_TEXTURE_2D, id);
switch (param)
{
case RL_TEXTURE_WRAP_S:
case RL_TEXTURE_WRAP_T:
{
if ((value == RL_WRAP_CLAMP_MIRROR) && !texClampMirrorSupported) TraceLog(WARNING, "Clamp mirror wrap mode not supported");
else glTexParameteri(GL_TEXTURE_2D, param, value);
} break;
case RL_TEXTURE_MAG_FILTER:
case RL_TEXTURE_MIN_FILTER: glTexParameteri(GL_TEXTURE_2D, param, value); break;
case RL_TEXTURE_ANISOTROPIC_FILTER:
{
if (value <= maxAnisotropicLevel) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, value);
else if (maxAnisotropicLevel > 0.0f)
{
TraceLog(WARNING, "[TEX ID %i] Maximum anisotropic filter level supported is %iX", id, maxAnisotropicLevel);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, value);
}
else TraceLog(WARNING, "Anisotropic filtering not supported");
} break;
default: break;
}
glBindTexture(GL_TEXTURE_2D, 0);
}
// Enable rendering to texture (fbo) // Enable rendering to texture (fbo)
void rlEnableRenderTexture(unsigned int id) void rlEnableRenderTexture(unsigned int id)
{ {
@ -1124,7 +1170,7 @@ void rlglInit(int width, int height)
// Check NPOT textures support // Check NPOT textures support
// NOTE: Only check on OpenGL ES, OpenGL 3.3 has NPOT textures full support as core feature // NOTE: Only check on OpenGL ES, OpenGL 3.3 has NPOT textures full support as core feature
if (strcmp(extList[i], (const char *)"GL_OES_texture_npot") == 0) npotSupported = true; if (strcmp(extList[i], (const char *)"GL_OES_texture_npot") == 0) npotSupported = true;
#endif #endif
// DDS texture compression support // DDS texture compression support
if ((strcmp(extList[i], (const char *)"GL_EXT_texture_compression_s3tc") == 0) || if ((strcmp(extList[i], (const char *)"GL_EXT_texture_compression_s3tc") == 0) ||
@ -1143,6 +1189,16 @@ void rlglInit(int width, int height)
// ASTC texture compression support // ASTC texture compression support
if (strcmp(extList[i], (const char *)"GL_KHR_texture_compression_astc_hdr") == 0) texCompASTCSupported = true; if (strcmp(extList[i], (const char *)"GL_KHR_texture_compression_astc_hdr") == 0) texCompASTCSupported = true;
// Anisotropic texture filter support
if (strcmp(extList[i], (const char *)"GL_EXT_texture_filter_anisotropic") == 0)
{
texAnisotropicFilterSupported = true;
glGetFloatv(0x84FF, &maxAnisotropicLevel); // GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT
}
// Clamp mirror wrap mode supported
if (strcmp(extList[i], (const char *)"GL_EXT_texture_mirror_clamp") == 0) texClampMirrorSupported = true;
} }
#ifdef _MSC_VER #ifdef _MSC_VER
@ -1162,6 +1218,9 @@ void rlglInit(int width, int height)
if (texCompETC2Supported) TraceLog(INFO, "[EXTENSION] ETC2/EAC compressed textures supported"); if (texCompETC2Supported) TraceLog(INFO, "[EXTENSION] ETC2/EAC compressed textures supported");
if (texCompPVRTSupported) TraceLog(INFO, "[EXTENSION] PVRT compressed textures supported"); if (texCompPVRTSupported) TraceLog(INFO, "[EXTENSION] PVRT compressed textures supported");
if (texCompASTCSupported) TraceLog(INFO, "[EXTENSION] ASTC compressed textures supported"); if (texCompASTCSupported) TraceLog(INFO, "[EXTENSION] ASTC compressed textures supported");
if (texAnisotropicFilterSupported) TraceLog(INFO, "[EXTENSION] Anisotropic textures filtering supported (max: %.0fX)", maxAnisotropicLevel);
if (texClampMirrorSupported) TraceLog(INFO, "[EXTENSION] Clamp mirror wrap texture mode supported");
// Initialize buffers, default shaders and default textures // Initialize buffers, default shaders and default textures
//---------------------------------------------------------- //----------------------------------------------------------
@ -1522,7 +1581,7 @@ RenderTexture2D rlglLoadRenderTexture(int width, int height)
target.texture.id = 0; target.texture.id = 0;
target.texture.width = width; target.texture.width = width;
target.texture.height = height; target.texture.height = height;
target.texture.format = UNCOMPRESSED_R8G8B8; target.texture.format = UNCOMPRESSED_R8G8B8A8;
target.texture.mipmaps = 1; target.texture.mipmaps = 1;
target.depth.id = 0; target.depth.id = 0;
@ -1539,7 +1598,7 @@ RenderTexture2D rlglLoadRenderTexture(int width, int height)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
#if defined(GRAPHICS_API_OPENGL_33) #if defined(GRAPHICS_API_OPENGL_33)
@ -1687,6 +1746,7 @@ void rlglGenerateMipmaps(Texture2D texture)
#endif #endif
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
//glHint(GL_GENERATE_MIPMAP_HINT, GL_DONT_CARE); // Hint for mipmaps generation algorythm: GL_FASTEST, GL_NICEST, GL_DONT_CARE
glGenerateMipmap(GL_TEXTURE_2D); // Generate mipmaps automatically glGenerateMipmap(GL_TEXTURE_2D); // Generate mipmaps automatically
TraceLog(INFO, "[TEX ID %i] Mipmaps generated automatically", texture.id); TraceLog(INFO, "[TEX ID %i] Mipmaps generated automatically", texture.id);
@ -2653,7 +2713,7 @@ void InitVrDevice(int vrDevice)
hmd.hResolution = 2160; // HMD horizontal resolution in pixels hmd.hResolution = 2160; // HMD horizontal resolution in pixels
hmd.vResolution = 1200; // HMD vertical resolution in pixels hmd.vResolution = 1200; // HMD vertical resolution in pixels
hmd.hScreenSize = 0.133793f; // HMD horizontal size in meters hmd.hScreenSize = 0.133793f; // HMD horizontal size in meters
hmd.vScreenSize = 0.0669; // HMD vertical size in meters hmd.vScreenSize = 0.0669f; // HMD vertical size in meters
hmd.vScreenCenter = 0.04678f; // HMD screen center in meters hmd.vScreenCenter = 0.04678f; // HMD screen center in meters
hmd.eyeToScreenDistance = 0.041f; // HMD distance between eye and display in meters hmd.eyeToScreenDistance = 0.041f; // HMD distance between eye and display in meters
hmd.lensSeparationDistance = 0.07f; // HMD lens separation distance in meters hmd.lensSeparationDistance = 0.07f; // HMD lens separation distance in meters
@ -2710,6 +2770,12 @@ bool IsVrDeviceReady(void)
return (vrDeviceReady || vrSimulator) && vrEnabled; return (vrDeviceReady || vrSimulator) && vrEnabled;
} }
// Detect if VR simulator is running
bool IsVrSimulator(void)
{
return vrSimulator;
}
// Enable/Disable VR experience (device or simulator) // Enable/Disable VR experience (device or simulator)
void ToggleVrMode(void) void ToggleVrMode(void)
{ {
@ -2728,16 +2794,13 @@ void ToggleVrMode(void)
#endif #endif
} }
// Update VR tracking (position and orientation) // Update VR tracking (position and orientation) and camera
void UpdateVrTracking(void) // NOTE: Camera (position, target, up) gets update with head tracking information
void UpdateVrTracking(Camera *camera)
{ {
#if defined(RLGL_OCULUS_SUPPORT) #if defined(RLGL_OCULUS_SUPPORT)
if (vrDeviceReady) UpdateOculusTracking(); if (vrDeviceReady) UpdateOculusTracking(camera);
else
#endif #endif
{
// TODO: Use alternative inputs (mouse, keyboard) to simulate tracking data (eyes position/orientation)
}
} }
// Begin Oculus drawing configuration // Begin Oculus drawing configuration
@ -3779,8 +3842,8 @@ static void SetStereoConfig(VrDeviceInfo hmd)
// Compute lens parameters // Compute lens parameters
float lensShift = (hmd.hScreenSize*0.25f - hmd.lensSeparationDistance*0.5f)/hmd.hScreenSize; float lensShift = (hmd.hScreenSize*0.25f - hmd.lensSeparationDistance*0.5f)/hmd.hScreenSize;
float leftLensCenter[2] = { 0.25 + lensShift, 0.5f }; float leftLensCenter[2] = { 0.25f + lensShift, 0.5f };
float rightLensCenter[2] = { 0.75 - lensShift, 0.5f }; float rightLensCenter[2] = { 0.75f - lensShift, 0.5f };
float leftScreenCenter[2] = { 0.25f, 0.5f }; float leftScreenCenter[2] = { 0.25f, 0.5f };
float rightScreenCenter[2] = { 0.75f, 0.5f }; float rightScreenCenter[2] = { 0.75f, 0.5f };
@ -3797,8 +3860,8 @@ static void SetStereoConfig(VrDeviceInfo hmd)
float normScreenWidth = 0.5f; float normScreenWidth = 0.5f;
float normScreenHeight = 1.0f; float normScreenHeight = 1.0f;
float scaleIn[2] = { 2/normScreenWidth, 2/normScreenHeight/aspect }; float scaleIn[2] = { 2.0f/normScreenWidth, 2.0f/normScreenHeight/aspect };
float scale[2] = { normScreenWidth*0.5/distortionScale, normScreenHeight*0.5*aspect/distortionScale }; float scale[2] = { normScreenWidth*0.5f/distortionScale, normScreenHeight*0.5f*aspect/distortionScale };
TraceLog(DEBUG, "VR: Distortion Shader: LeftLensCenter = { %f, %f }", leftLensCenter[0], leftLensCenter[1]); TraceLog(DEBUG, "VR: Distortion Shader: LeftLensCenter = { %f, %f }", leftLensCenter[0], leftLensCenter[1]);
TraceLog(DEBUG, "VR: Distortion Shader: RightLensCenter = { %f, %f }", rightLensCenter[0], rightLensCenter[1]); TraceLog(DEBUG, "VR: Distortion Shader: RightLensCenter = { %f, %f }", rightLensCenter[0], rightLensCenter[1]);
@ -4076,7 +4139,7 @@ OCULUSAPI void CloseOculusDevice(void)
} }
// Update Oculus head position-orientation tracking // Update Oculus head position-orientation tracking
OCULUSAPI void UpdateOculusTracking(void) OCULUSAPI void UpdateOculusTracking(Camera *camera)
{ {
frameIndex++; frameIndex++;
@ -4086,6 +4149,10 @@ OCULUSAPI void UpdateOculusTracking(void)
layer.eyeLayer.RenderPose[0] = eyePoses[0]; layer.eyeLayer.RenderPose[0] = eyePoses[0];
layer.eyeLayer.RenderPose[1] = eyePoses[1]; layer.eyeLayer.RenderPose[1] = eyePoses[1];
// TODO: Update external camera with eyePoses data (position, orientation)
// NOTE: We can simplify to simple camera if we consider IPD and HMD device configuration again later
// it will be useful for the user to draw, lets say, billboards oriented to camera
// Get session status information // Get session status information
ovrSessionStatus sessionStatus; ovrSessionStatus sessionStatus;
ovr_GetSessionStatus(session, &sessionStatus); ovr_GetSessionStatus(session, &sessionStatus);

View File

@ -90,15 +90,33 @@
#define MAX_QUADS_BATCH 1024 // Be careful with text, every letter maps a quad #define MAX_QUADS_BATCH 1024 // Be careful with text, every letter maps a quad
#endif #endif
// Texture parameters (equivalent to OpenGL defines)
#define RL_TEXTURE_WRAP_S 0x2802 // GL_TEXTURE_WRAP_S
#define RL_TEXTURE_WRAP_T 0x2803 // GL_TEXTURE_WRAP_T
#define RL_TEXTURE_MAG_FILTER 0x2800 // GL_TEXTURE_MAG_FILTER
#define RL_TEXTURE_MIN_FILTER 0x2801 // GL_TEXTURE_MIN_FILTER
#define RL_TEXTURE_ANISOTROPIC_FILTER 0x3000 // Anisotropic filter (custom identifier)
#define RL_FILTER_NEAREST 0x2600 // GL_NEAREST
#define RL_FILTER_LINEAR 0x2601 // GL_LINEAR
#define RL_FILTER_MIP_NEAREST 0x2700 // GL_NEAREST_MIPMAP_NEAREST
#define RL_FILTER_NEAREST_MIP_LINEAR 0x2702 // GL_NEAREST_MIPMAP_LINEAR
#define RL_FILTER_LINEAR_MIP_NEAREST 0x2701 // GL_LINEAR_MIPMAP_NEAREST
#define RL_FILTER_MIP_LINEAR 0x2703 // GL_LINEAR_MIPMAP_LINEAR
#define RL_WRAP_REPEAT 0x2901 // GL_REPEAT
#define RL_WRAP_CLAMP 0x812F // GL_CLAMP_TO_EDGE
#define RL_WRAP_CLAMP_MIRROR 0x8742 // GL_MIRROR_CLAMP_EXT
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Types and Structures Definition // Types and Structures Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
typedef enum { OPENGL_11 = 1, OPENGL_21, OPENGL_33, OPENGL_ES_20 } GlVersion;
typedef enum { RL_PROJECTION, RL_MODELVIEW, RL_TEXTURE } MatrixMode; typedef enum { RL_PROJECTION, RL_MODELVIEW, RL_TEXTURE } MatrixMode;
typedef enum { RL_LINES, RL_TRIANGLES, RL_QUADS } DrawMode; typedef enum { RL_LINES, RL_TRIANGLES, RL_QUADS } DrawMode;
typedef enum { OPENGL_11 = 1, OPENGL_21, OPENGL_33, OPENGL_ES_20 } GlVersion;
#if defined(RLGL_STANDALONE) #if defined(RLGL_STANDALONE)
#ifndef __cplusplus #ifndef __cplusplus
// Boolean type // Boolean type
@ -236,6 +254,21 @@ typedef enum { OPENGL_11 = 1, OPENGL_21, OPENGL_33, OPENGL_ES_20 } GlVersion;
// Light types // Light types
typedef enum { LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT } LightType; typedef enum { LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT } LightType;
// Texture parameters: filter mode
// NOTE 1: Filtering considers mipmaps if available in the texture
// NOTE 2: Filter is accordingly set for minification and magnification
typedef enum {
FILTER_POINT = 0, // No filter, just pixel aproximation
FILTER_BILINEAR, // Linear filtering
FILTER_TRILINEAR, // Trilinear filtering (linear with mipmaps)
FILTER_ANISOTROPIC_4X, // Anisotropic filtering 4x
FILTER_ANISOTROPIC_8X, // Anisotropic filtering 8x
FILTER_ANISOTROPIC_16X, // Anisotropic filtering 16x
} TextureFilterMode;
// Texture parameters: wrap mode
typedef enum { WRAP_REPEAT = 0, WRAP_CLAMP, WRAP_MIRROR } TextureWrapMode;
// Color blending modes (pre-defined) // Color blending modes (pre-defined)
typedef enum { BLEND_ALPHA = 0, BLEND_ADDITIVE, BLEND_MULTIPLIED } BlendMode; typedef enum { BLEND_ALPHA = 0, BLEND_ADDITIVE, BLEND_MULTIPLIED } BlendMode;
@ -296,6 +329,7 @@ void rlColor4f(float x, float y, float z, float w); // Define one vertex (color)
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
void rlEnableTexture(unsigned int id); // Enable texture usage void rlEnableTexture(unsigned int id); // Enable texture usage
void rlDisableTexture(void); // Disable texture usage void rlDisableTexture(void); // Disable texture usage
void rlTextureParameters(unsigned int id, int param, int value); // Set texture parameters (filter, wrap)
void rlEnableRenderTexture(unsigned int id); // Enable render texture (fbo) void rlEnableRenderTexture(unsigned int id); // Enable render texture (fbo)
void rlDisableRenderTexture(void); // Disable render texture (fbo), return to default framebuffer void rlDisableRenderTexture(void); // Disable render texture (fbo), return to default framebuffer
void rlEnableDepthTest(void); // Enable depth test void rlEnableDepthTest(void); // Enable depth test
@ -375,13 +409,13 @@ float *MatrixToFloat(Matrix mat);
void InitVrDevice(int vrDevice); // Init VR device void InitVrDevice(int vrDevice); // Init VR device
void CloseVrDevice(void); // Close VR device void CloseVrDevice(void); // Close VR device
bool IsVrDeviceReady(void); // Detect if VR device (or simulator) is ready bool IsVrDeviceReady(void); // Detect if VR device (or simulator) is ready
void UpdateVrTracking(void); // Update VR tracking (position and orientation) void UpdateVrTracking(Camera *camera); // Update VR tracking (position and orientation) and camera
void ToggleVrMode(void); // Enable/Disable VR experience (device or simulator) void ToggleVrMode(void); // Enable/Disable VR experience (device or simulator)
// Oculus Rift API for direct access the device (no simulator) // Oculus Rift API for direct access the device (no simulator)
bool InitOculusDevice(void); // Initialize Oculus device (returns true if success) bool InitOculusDevice(void); // Initialize Oculus device (returns true if success)
void CloseOculusDevice(void); // Close Oculus device void CloseOculusDevice(void); // Close Oculus device
void UpdateOculusTracking(void); // Update Oculus head position-orientation tracking void UpdateOculusTracking(Camera *camera); // Update Oculus head position-orientation tracking (and camera)
void BeginOculusDrawing(void); // Setup Oculus buffers for drawing void BeginOculusDrawing(void); // Setup Oculus buffers for drawing
void EndOculusDrawing(void); // Finish Oculus drawing and blit framebuffer to mirror void EndOculusDrawing(void); // Finish Oculus drawing and blit framebuffer to mirror
#endif #endif

View File

@ -2824,6 +2824,28 @@ int lua_IsAudioDeviceReady(lua_State* L)
return 1; return 1;
} }
int lua_LoadWave(lua_State* L)
{
const char * arg1 = LuaGetArgument_string(L, 1);
Wave result = LoadWave((char *)arg1);
LuaPush_Wave(L, result);
return 1;
}
int lua_LoadWaveEx(lua_State* L)
{
// TODO: Wave LoadWaveEx(float *data, int sampleCount, int sampleRate, int sampleSize, int channels);
int arg1 = 0;
int arg2 = LuaGetArgument_int(L, 2);
int arg3 = LuaGetArgument_int(L, 3);
int arg4 = LuaGetArgument_int(L, 4);
int arg5 = LuaGetArgument_int(L, 5);
Wave result = LoadWaveEx(arg1, arg2, arg3, arg4, arg5);
LuaPush_Wave(L, result);
return 1;
}
int lua_LoadSound(lua_State* L) int lua_LoadSound(lua_State* L)
{ {
const char * arg1 = LuaGetArgument_string(L, 1); const char * arg1 = LuaGetArgument_string(L, 1);
@ -2849,6 +2871,22 @@ int lua_LoadSoundFromRES(lua_State* L)
return 1; return 1;
} }
int lua_UpdateSound(lua_State* L)
{
Sound arg1 = LuaGetArgument_Sound(L, 1);
const char * arg2 = LuaGetArgument_string(L, 2);
int * arg3 = LuaGetArgument_int(L, 3);
UpdateSound(arg1, arg2, arg3);
return 0;
}
int lua_UnloadWave(lua_State* L)
{
Wave arg1 = LuaGetArgument_Wave(L, 1);
UnloadWave(arg1);
return 0;
}
int lua_UnloadSound(lua_State* L) int lua_UnloadSound(lua_State* L)
{ {
Sound arg1 = LuaGetArgument_Sound(L, 1); Sound arg1 = LuaGetArgument_Sound(L, 1);
@ -2908,6 +2946,43 @@ int lua_SetSoundPitch(lua_State* L)
return 0; return 0;
} }
int lua_WaveFormat(lua_State* L)
{
Wave arg1 = LuaGetArgument_Wave(L, 1);
int arg2 = LuaGetArgument_int(L, 2);
int arg3 = LuaGetArgument_int(L, 3);
int arg4 = LuaGetArgument_int(L, 4);
WaveFormat(arg1, arg2, arg3, arg4);
return 0;
}
int lua_LoadMusicStream(lua_State* L)
{
Wave arg1 = LuaGetArgument_Wave(L, 1);
Wave result = WaveCopy(arg1);
LuaPush_Wave(L, result);
return 1;
}
int lua_WaveCrop(lua_State* L)
{
Wave arg1 = LuaGetArgument_Wave(L, 1);
int arg2 = LuaGetArgument_int(L, 2);
int arg3 = LuaGetArgument_int(L, 3);
WaveCrop(arg1, arg2, arg3);
return 0;
}
int lua_GetWaveData(lua_State* L)
{
// TODO: float *GetWaveData(Wave wave);
Wave arg1 = LuaGetArgument_Wave(L, 1);
float result = GetWaveData(arg1);
LuaPush_float(L, result);
return 1;
}
int lua_LoadMusicStream(lua_State* L) int lua_LoadMusicStream(lua_State* L)
{ {
const char * arg1 = LuaGetArgument_string(L, 1); const char * arg1 = LuaGetArgument_string(L, 1);
@ -3799,9 +3874,13 @@ static luaL_Reg raylib_functions[] = {
REG(InitAudioDevice) REG(InitAudioDevice)
REG(CloseAudioDevice) REG(CloseAudioDevice)
REG(IsAudioDeviceReady) REG(IsAudioDeviceReady)
REG(LoadWave)
REG(LoadWaveEx)
REG(LoadSound) REG(LoadSound)
REG(LoadSoundFromWave) REG(LoadSoundFromWave)
REG(LoadSoundFromRES) REG(LoadSoundFromRES)
REG(UpdateSound)
REG(UnloadWave)
REG(UnloadSound) REG(UnloadSound)
REG(PlaySound) REG(PlaySound)
REG(PauseSound) REG(PauseSound)
@ -3810,6 +3889,10 @@ static luaL_Reg raylib_functions[] = {
REG(IsSoundPlaying) REG(IsSoundPlaying)
REG(SetSoundVolume) REG(SetSoundVolume)
REG(SetSoundPitch) REG(SetSoundPitch)
REG(WaveFormat)
REG(WaveCopy)
REG(WaveCrop)
REG(GetWaveData)
REG(LoadMusicStream) REG(LoadMusicStream)
REG(UnloadMusicStream) REG(UnloadMusicStream)

View File

@ -90,7 +90,7 @@ static const char fStandardShaderStr[] =
" if (diff > 0.0)\n" " if (diff > 0.0)\n"
" {\n" " {\n"
" vec3 h = normalize(-l.direction + v);\n" " vec3 h = normalize(-l.direction + v);\n"
" spec = pow(dot(n, h), 3.0 + glossiness)*s;\n" " spec = pow(abs(dot(n, h)), 3.0 + glossiness)*s;\n"
" }\n" " }\n"
" return (diff*l.diffuse.rgb + spec*colSpecular.rgb);\n" " return (diff*l.diffuse.rgb + spec*colSpecular.rgb);\n"
"}\n" "}\n"
@ -103,7 +103,7 @@ static const char fStandardShaderStr[] =
" if (diff > 0.0)\n" " if (diff > 0.0)\n"
" {\n" " {\n"
" vec3 h = normalize(lightDir + v);\n" " vec3 h = normalize(lightDir + v);\n"
" spec = pow(dot(n, h), 3.0 + glossiness)*s;\n" " spec = pow(abs(dot(n, h)), 3.0 + glossiness)*s;\n"
" }\n" " }\n"
" return (diff*l.intensity*l.diffuse.rgb + spec*colSpecular.rgb);\n" " return (diff*l.intensity*l.diffuse.rgb + spec*colSpecular.rgb);\n"
"}\n" "}\n"
@ -124,7 +124,7 @@ static const char fStandardShaderStr[] =
" if (diffAttenuation > 0.0)\n" " if (diffAttenuation > 0.0)\n"
" {\n" " {\n"
" vec3 h = normalize(lightDir + v);\n" " vec3 h = normalize(lightDir + v);\n"
" spec = pow(dot(n, h), 3.0 + glossiness)*s;\n" " spec = pow(abs(dot(n, h)), 3.0 + glossiness)*s;\n"
" }\n" " }\n"
" return (falloff*(diffAttenuation*l.diffuse.rgb + spec*colSpecular.rgb));\n" " return (falloff*(diffAttenuation*l.diffuse.rgb + spec*colSpecular.rgb));\n"
"}\n" "}\n"
@ -152,9 +152,9 @@ static const char fStandardShaderStr[] =
" }\n" " }\n"
" float spec = 1.0;\n" " float spec = 1.0;\n"
#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21) #if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21)
" if (useSpecular == 1) spec *= normalize(texture2D(texture2, fragTexCoord).r);\n" " if (useSpecular == 1) spec = texture2D(texture2, fragTexCoord).r;\n"
#elif defined(GRAPHICS_API_OPENGL_33) #elif defined(GRAPHICS_API_OPENGL_33)
" if (useSpecular == 1) spec *= normalize(texture(texture2, fragTexCoord).r);\n" " if (useSpecular == 1) spec = texture(texture2, fragTexCoord).r;\n"
#endif #endif
" for (int i = 0; i < maxLights; i++)\n" " for (int i = 0; i < maxLights; i++)\n"
" {\n" " {\n"

View File

@ -4,7 +4,7 @@
* *
* Basic functions to draw 2d Shapes and check collisions * Basic functions to draw 2d Shapes and check collisions
* *
* Copyright (c) 2014 Ramon Santamaria (@raysan5) * Copyright (c) 2014-2016 Ramon Santamaria (@raysan5)
* *
* This software is provided "as-is", without any express or implied warranty. In no event * This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software. * will the authors be held liable for any damages arising from the use of this software.
@ -25,9 +25,8 @@
#include "raylib.h" #include "raylib.h"
#include <stdlib.h> // Required for abs() function #include <stdlib.h> // Required for: abs()
#include <math.h> // Math related functions, sin() and cos() used on DrawCircle* #include <math.h> // Required for: sinf(), cosf(), sqrtf()
// sqrt() and pow() and abs() used on CheckCollision*
#include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3+ or ES2 #include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3+ or ES2
@ -71,7 +70,7 @@ void DrawPixelV(Vector2 position, Color color)
rlBegin(RL_LINES); rlBegin(RL_LINES);
rlColor4ub(color.r, color.g, color.b, color.a); rlColor4ub(color.r, color.g, color.b, color.a);
rlVertex2f(position.x, position.y); rlVertex2f(position.x, position.y);
rlVertex2i(position.x + 1, position.y + 1); rlVertex2f(position.x + 1.0f, position.y + 1.0f);
rlEnd(); rlEnd();
} }
@ -98,7 +97,7 @@ void DrawLineV(Vector2 startPos, Vector2 endPos, Color color)
// Draw a color-filled circle // Draw a color-filled circle
void DrawCircle(int centerX, int centerY, float radius, Color color) void DrawCircle(int centerX, int centerY, float radius, Color color)
{ {
DrawCircleV((Vector2){ centerX, centerY }, radius, color); DrawCircleV((Vector2){ (float)centerX, (float)centerY }, radius, color);
} }
// Draw a gradient-filled circle // Draw a gradient-filled circle
@ -111,9 +110,9 @@ void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Co
rlColor4ub(color1.r, color1.g, color1.b, color1.a); rlColor4ub(color1.r, color1.g, color1.b, color1.a);
rlVertex2i(centerX, centerY); rlVertex2i(centerX, centerY);
rlColor4ub(color2.r, color2.g, color2.b, color2.a); rlColor4ub(color2.r, color2.g, color2.b, color2.a);
rlVertex2f(centerX + sin(DEG2RAD*i)*radius, centerY + cos(DEG2RAD*i)*radius); rlVertex2f(centerX + sinf(DEG2RAD*i)*radius, centerY + cosf(DEG2RAD*i)*radius);
rlColor4ub(color2.r, color2.g, color2.b, color2.a); rlColor4ub(color2.r, color2.g, color2.b, color2.a);
rlVertex2f(centerX + sin(DEG2RAD*(i + 10))*radius, centerY + cos(DEG2RAD*(i + 10))*radius); rlVertex2f(centerX + sinf(DEG2RAD*(i + 10))*radius, centerY + cosf(DEG2RAD*(i + 10))*radius);
} }
rlEnd(); rlEnd();
} }
@ -129,9 +128,9 @@ void DrawCircleV(Vector2 center, float radius, Color color)
{ {
rlColor4ub(color.r, color.g, color.b, color.a); rlColor4ub(color.r, color.g, color.b, color.a);
rlVertex2i(center.x, center.y); rlVertex2f(center.x, center.y);
rlVertex2f(center.x + sin(DEG2RAD*i)*radius, center.y + cos(DEG2RAD*i)*radius); rlVertex2f(center.x + sinf(DEG2RAD*i)*radius, center.y + cosf(DEG2RAD*i)*radius);
rlVertex2f(center.x + sin(DEG2RAD*(i + 10))*radius, center.y + cos(DEG2RAD*(i + 10))*radius); rlVertex2f(center.x + sinf(DEG2RAD*(i + 10))*radius, center.y + cosf(DEG2RAD*(i + 10))*radius);
} }
rlEnd(); rlEnd();
} }
@ -144,10 +143,10 @@ void DrawCircleV(Vector2 center, float radius, Color color)
{ {
rlColor4ub(color.r, color.g, color.b, color.a); rlColor4ub(color.r, color.g, color.b, color.a);
rlVertex2i(center.x, center.y); rlVertex2f(center.x, center.y);
rlVertex2f(center.x + sin(DEG2RAD*i)*radius, center.y + cos(DEG2RAD*i)*radius); rlVertex2f(center.x + sinf(DEG2RAD*i)*radius, center.y + cosf(DEG2RAD*i)*radius);
rlVertex2f(center.x + sin(DEG2RAD*(i + 10))*radius, center.y + cos(DEG2RAD*(i + 10))*radius); rlVertex2f(center.x + sinf(DEG2RAD*(i + 10))*radius, center.y + cosf(DEG2RAD*(i + 10))*radius);
rlVertex2f(center.x + sin(DEG2RAD*(i + 20))*radius, center.y + cos(DEG2RAD*(i + 20))*radius); rlVertex2f(center.x + sinf(DEG2RAD*(i + 20))*radius, center.y + cosf(DEG2RAD*(i + 20))*radius);
} }
rlEnd(); rlEnd();
@ -164,8 +163,8 @@ void DrawCircleLines(int centerX, int centerY, float radius, Color color)
// NOTE: Circle outline is drawn pixel by pixel every degree (0 to 360) // NOTE: Circle outline is drawn pixel by pixel every degree (0 to 360)
for (int i = 0; i < 360; i += 10) for (int i = 0; i < 360; i += 10)
{ {
rlVertex2f(centerX + sin(DEG2RAD*i)*radius, centerY + cos(DEG2RAD*i)*radius); rlVertex2f(centerX + sinf(DEG2RAD*i)*radius, centerY + cosf(DEG2RAD*i)*radius);
rlVertex2f(centerX + sin(DEG2RAD*(i + 10))*radius, centerY + cos(DEG2RAD*(i + 10))*radius); rlVertex2f(centerX + sinf(DEG2RAD*(i + 10))*radius, centerY + cosf(DEG2RAD*(i + 10))*radius);
} }
rlEnd(); rlEnd();
} }
@ -330,9 +329,9 @@ void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color col
{ {
rlColor4ub(color.r, color.g, color.b, color.a); rlColor4ub(color.r, color.g, color.b, color.a);
rlVertex2i(0, 0); rlVertex2f(0, 0);
rlVertex2f(sin(DEG2RAD*i)*radius, cos(DEG2RAD*i)*radius); rlVertex2f(sinf(DEG2RAD*i)*radius, cosf(DEG2RAD*i)*radius);
rlVertex2f(sin(DEG2RAD*(i + 360/sides))*radius, cos(DEG2RAD*(i + 360/sides))*radius); rlVertex2f(sinf(DEG2RAD*(i + 360/sides))*radius, cosf(DEG2RAD*(i + 360/sides))*radius);
} }
rlEnd(); rlEnd();
rlPopMatrix(); rlPopMatrix();
@ -434,7 +433,7 @@ bool CheckCollisionCircles(Vector2 center1, float radius1, Vector2 center2, floa
float dx = center2.x - center1.x; // X distance between centers float dx = center2.x - center1.x; // X distance between centers
float dy = center2.y - center1.y; // Y distance between centers float dy = center2.y - center1.y; // Y distance between centers
float distance = sqrt(dx*dx + dy*dy); // Distance between centers float distance = sqrtf(dx*dx + dy*dy); // Distance between centers
if (distance <= (radius1 + radius2)) collision = true; if (distance <= (radius1 + radius2)) collision = true;
@ -457,7 +456,7 @@ bool CheckCollisionCircleRec(Vector2 center, float radius, Rectangle rec)
if (dx <= (rec.width/2)) { return true; } if (dx <= (rec.width/2)) { return true; }
if (dy <= (rec.height/2)) { return true; } if (dy <= (rec.height/2)) { return true; }
float cornerDistanceSq = pow(dx - rec.width/2, 2) + pow(dy - rec.height/2, 2); float cornerDistanceSq = (dx - rec.width/2)*(dx - rec.width/2) + (dy - rec.height/2)*(dy - rec.height/2);
return (cornerDistanceSq <= (radius*radius)); return (cornerDistanceSq <= (radius*radius));
} }

View File

@ -4,7 +4,7 @@
* *
* Basic functions to load SpriteFonts and draw Text * Basic functions to load SpriteFonts and draw Text
* *
* Copyright (c) 2014 Ramon Santamaria (@raysan5) * Copyright (c) 2014-2016 Ramon Santamaria (@raysan5)
* *
* This software is provided "as-is", without any express or implied warranty. In no event * This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software. * will the authors be held liable for any damages arising from the use of this software.
@ -30,9 +30,10 @@
#include <stdarg.h> // Required for: va_list, va_start(), vfprintf(), va_end() #include <stdarg.h> // Required for: va_list, va_start(), vfprintf(), va_end()
#include <stdio.h> // Required for: FILE, fopen(), fclose(), fscanf(), feof(), rewind(), fgets() #include <stdio.h> // Required for: FILE, fopen(), fclose(), fscanf(), feof(), rewind(), fgets()
#include "utils.h" // Required for: GetExtension() #include "utils.h" // Required for: GetExtension(), GetNextPOT()
// Following libs are used on LoadTTF() // Following libs are used on LoadTTF()
//#define STBTT_STATIC
#define STB_TRUETYPE_IMPLEMENTATION #define STB_TRUETYPE_IMPLEMENTATION
#include "external/stb_truetype.h" // Required for: stbtt_BakeFontBitmap() #include "external/stb_truetype.h" // Required for: stbtt_BakeFontBitmap()
@ -43,7 +44,6 @@
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Defines and Macros // Defines and Macros
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
#define FONT_FIRST_CHAR 32 // NOTE: Expected first char for a sprite font
#define MAX_FORMATTEXT_LENGTH 64 #define MAX_FORMATTEXT_LENGTH 64
#define MAX_SUBTEXT_LENGTH 64 #define MAX_SUBTEXT_LENGTH 64
@ -68,12 +68,12 @@ static SpriteFont defaultFont; // Default font provided by raylib
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module specific Functions Declaration // Module specific Functions Declaration
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
static int GetCharIndex(SpriteFont font, int letter);
static SpriteFont LoadImageFont(Image image, Color key, int firstChar); // Load a Image font file (XNA style) static SpriteFont LoadImageFont(Image image, Color key, int firstChar); // Load a Image font file (XNA style)
static SpriteFont LoadRBMF(const char *fileName); // Load a rBMF font file (raylib BitMap Font) static SpriteFont LoadRBMF(const char *fileName); // Load a rBMF font file (raylib BitMap Font)
static SpriteFont LoadBMFont(const char *fileName); // Load a BMFont file (AngelCode font file) static SpriteFont LoadBMFont(const char *fileName); // Load a BMFont file (AngelCode font file)
static SpriteFont LoadTTF(const char *fileName, int fontSize, int numChars, int *fontChars); // Load spritefont from TTF data
// Generate a sprite font image from TTF data
static SpriteFont LoadTTF(const char *fileName, int fontSize, int firstChar, int numChars);
extern void LoadDefaultFont(void); extern void LoadDefaultFont(void);
extern void UnloadDefaultFont(void); extern void UnloadDefaultFont(void);
@ -198,7 +198,7 @@ extern void LoadDefaultFont(void)
for (int i = 0; i < defaultFont.numChars; i++) for (int i = 0; i < defaultFont.numChars; i++)
{ {
defaultFont.charValues[i] = FONT_FIRST_CHAR + i; // First char is 32 defaultFont.charValues[i] = 32 + i; // First char is 32
defaultFont.charRecs[i].x = currentPosX; defaultFont.charRecs[i].x = currentPosX;
defaultFont.charRecs[i].y = charsDivisor + currentLine*(charsHeight + charsDivisor); defaultFont.charRecs[i].y = charsDivisor + currentLine*(charsHeight + charsDivisor);
@ -249,17 +249,18 @@ SpriteFont LoadSpriteFont(const char *fileName)
// Default hardcoded values for ttf file loading // Default hardcoded values for ttf file loading
#define DEFAULT_TTF_FONTSIZE 32 // Font first character (32 - space) #define DEFAULT_TTF_FONTSIZE 32 // Font first character (32 - space)
#define DEFAULT_TTF_NUMCHARS 95 // ASCII 32..126 is 95 glyphs #define DEFAULT_TTF_NUMCHARS 95 // ASCII 32..126 is 95 glyphs
#define DEFAULT_FIRST_CHAR 32 // Expected first char for image spritefont
SpriteFont spriteFont = { 0 }; SpriteFont spriteFont = { 0 };
// Check file extension // Check file extension
if (strcmp(GetExtension(fileName),"rbmf") == 0) spriteFont = LoadRBMF(fileName); if (strcmp(GetExtension(fileName),"rbmf") == 0) spriteFont = LoadRBMF(fileName);
else if (strcmp(GetExtension(fileName),"ttf") == 0) spriteFont = LoadTTF(fileName, DEFAULT_TTF_FONTSIZE, FONT_FIRST_CHAR, DEFAULT_TTF_NUMCHARS); else if (strcmp(GetExtension(fileName),"ttf") == 0) spriteFont = LoadSpriteFontTTF(fileName, DEFAULT_TTF_FONTSIZE, 0, NULL);
else if (strcmp(GetExtension(fileName),"fnt") == 0) spriteFont = LoadBMFont(fileName); else if (strcmp(GetExtension(fileName),"fnt") == 0) spriteFont = LoadBMFont(fileName);
else else
{ {
Image image = LoadImage(fileName); Image image = LoadImage(fileName);
if (image.data != NULL) spriteFont = LoadImageFont(image, MAGENTA, FONT_FIRST_CHAR); if (image.data != NULL) spriteFont = LoadImageFont(image, MAGENTA, DEFAULT_FIRST_CHAR);
UnloadImage(image); UnloadImage(image);
} }
@ -268,6 +269,38 @@ SpriteFont LoadSpriteFont(const char *fileName)
TraceLog(WARNING, "[%s] SpriteFont could not be loaded, using default font", fileName); TraceLog(WARNING, "[%s] SpriteFont could not be loaded, using default font", fileName);
spriteFont = GetDefaultFont(); spriteFont = GetDefaultFont();
} }
else SetTextureFilter(spriteFont.texture, FILTER_POINT); // By default we set point filter (best performance)
return spriteFont;
}
// Load SpriteFont from TTF file with custom parameters
// NOTE: You can pass an array with desired characters, those characters should be available in the font
// if array is NULL, default char set is selected 32..126
SpriteFont LoadSpriteFontTTF(const char *fileName, int fontSize, int numChars, int *fontChars)
{
SpriteFont spriteFont = { 0 };
if (strcmp(GetExtension(fileName),"ttf") == 0)
{
if ((fontChars == NULL) || (numChars == 0))
{
int totalChars = 95; // Default charset [32..126]
int *defaultFontChars = (int *)malloc(totalChars*sizeof(int));
for (int i = 0; i < totalChars; i++) defaultFontChars[i] = i + 32; // Default first character: SPACE[32]
spriteFont = LoadTTF(fileName, fontSize, totalChars, defaultFontChars);
}
else spriteFont = LoadTTF(fileName, fontSize, numChars, fontChars);
}
if (spriteFont.texture.id == 0)
{
TraceLog(WARNING, "[%s] SpriteFont could not be generated, using default font", fileName);
spriteFont = GetDefaultFont();
}
return spriteFont; return spriteFont;
} }
@ -293,13 +326,17 @@ void UnloadSpriteFont(SpriteFont spriteFont)
// NOTE: chars spacing is proportional to fontSize // NOTE: chars spacing is proportional to fontSize
void DrawText(const char *text, int posX, int posY, int fontSize, Color color) void DrawText(const char *text, int posX, int posY, int fontSize, Color color)
{ {
Vector2 position = { (float)posX, (float)posY }; // Check if default font has been loaded
if (defaultFont.texture.id != 0)
{
Vector2 position = { (float)posX, (float)posY };
int defaultFontSize = 10; // Default Font chars height in pixel int defaultFontSize = 10; // Default Font chars height in pixel
if (fontSize < defaultFontSize) fontSize = defaultFontSize; if (fontSize < defaultFontSize) fontSize = defaultFontSize;
int spacing = fontSize/defaultFontSize; int spacing = fontSize/defaultFontSize;
DrawTextEx(defaultFont, text, position, (float)fontSize, spacing, color); DrawTextEx(GetDefaultFont(), text, position, (float)fontSize, spacing, color);
}
} }
// Draw text using SpriteFont // Draw text using SpriteFont
@ -321,22 +358,18 @@ void DrawTextEx(SpriteFont spriteFont, const char *text, Vector2 position, float
for (int i = 0; i < length; i++) for (int i = 0; i < length; i++)
{ {
// TODO: Right now we are supposing characters that follow a continous order and start at FONT_FIRST_CHAR,
// this sytem can be improved to support any characters order and init value...
// An intermediate table could be created to link char values with predefined char position index in chars rectangle array
if ((unsigned char)text[i] == 0xc2) // UTF-8 encoding identification HACK! if ((unsigned char)text[i] == 0xc2) // UTF-8 encoding identification HACK!
{ {
// Support UTF-8 encoded values from [0xc2 0x80] -> [0xc2 0xbf](¿) // Support UTF-8 encoded values from [0xc2 0x80] -> [0xc2 0xbf](¿)
letter = (unsigned char)text[i + 1]; letter = (unsigned char)text[i + 1];
rec = spriteFont.charRecs[letter - FONT_FIRST_CHAR]; rec = spriteFont.charRecs[GetCharIndex(spriteFont, (int)letter)];
i++; i++;
} }
else if ((unsigned char)text[i] == 0xc3) // UTF-8 encoding identification HACK! else if ((unsigned char)text[i] == 0xc3) // UTF-8 encoding identification HACK!
{ {
// Support UTF-8 encoded values from [0xc3 0x80](À) -> [0xc3 0xbf](ÿ) // Support UTF-8 encoded values from [0xc3 0x80](À) -> [0xc3 0xbf](ÿ)
letter = (unsigned char)text[i + 1]; letter = (unsigned char)text[i + 1];
rec = spriteFont.charRecs[letter - FONT_FIRST_CHAR + 64]; rec = spriteFont.charRecs[GetCharIndex(spriteFont, (int)letter + 64)];
i++; i++;
} }
else else
@ -348,17 +381,19 @@ void DrawTextEx(SpriteFont spriteFont, const char *text, Vector2 position, float
textOffsetX = 0; textOffsetX = 0;
rec.x = -1; rec.x = -1;
} }
else rec = spriteFont.charRecs[(int)text[i] - FONT_FIRST_CHAR]; else rec = spriteFont.charRecs[GetCharIndex(spriteFont, (int)text[i])];
} }
if (rec.x > 0) if (rec.x >= 0)
{ {
DrawTexturePro(spriteFont.texture, rec, (Rectangle){ position.x + textOffsetX + spriteFont.charOffsets[(int)text[i] - FONT_FIRST_CHAR].x*scaleFactor, int index = GetCharIndex(spriteFont, (int)text[i]);
position.y + textOffsetY + spriteFont.charOffsets[(int)text[i] - FONT_FIRST_CHAR].y*scaleFactor,
DrawTexturePro(spriteFont.texture, rec, (Rectangle){ position.x + textOffsetX + spriteFont.charOffsets[index].x*scaleFactor,
position.y + textOffsetY + spriteFont.charOffsets[index].y*scaleFactor,
rec.width*scaleFactor, rec.height*scaleFactor} , (Vector2){ 0, 0 }, 0.0f, tint); rec.width*scaleFactor, rec.height*scaleFactor} , (Vector2){ 0, 0 }, 0.0f, tint);
if (spriteFont.charAdvanceX[(int)text[i] - FONT_FIRST_CHAR] == 0) textOffsetX += (rec.width*scaleFactor + spacing); if (spriteFont.charAdvanceX[index] == 0) textOffsetX += (rec.width*scaleFactor + spacing);
else textOffsetX += (spriteFont.charAdvanceX[(int)text[i] - FONT_FIRST_CHAR]*scaleFactor + spacing); else textOffsetX += (spriteFont.charAdvanceX[index]*scaleFactor + spacing);
} }
} }
} }
@ -404,13 +439,17 @@ const char *SubText(const char *text, int position, int length)
// Measure string width for default font // Measure string width for default font
int MeasureText(const char *text, int fontSize) int MeasureText(const char *text, int fontSize)
{ {
Vector2 vec; Vector2 vec = { 0.0f, 0.0f };
int defaultFontSize = 10; // Default Font chars height in pixel // Check if default font has been loaded
if (fontSize < defaultFontSize) fontSize = defaultFontSize; if (defaultFont.texture.id != 0)
int spacing = fontSize/defaultFontSize; {
int defaultFontSize = 10; // Default Font chars height in pixel
if (fontSize < defaultFontSize) fontSize = defaultFontSize;
int spacing = fontSize/defaultFontSize;
vec = MeasureTextEx(defaultFont, text, fontSize, spacing); vec = MeasureTextEx(GetDefaultFont(), text, fontSize, spacing);
}
return (int)vec.x; return (int)vec.x;
} }
@ -434,8 +473,10 @@ Vector2 MeasureTextEx(SpriteFont spriteFont, const char *text, int fontSize, int
if (text[i] != '\n') if (text[i] != '\n')
{ {
if (spriteFont.charAdvanceX[(int)text[i] - FONT_FIRST_CHAR] != 0) textWidth += spriteFont.charAdvanceX[(int)text[i] - FONT_FIRST_CHAR]; int index = GetCharIndex(spriteFont, (int)text[i]);
else textWidth += (spriteFont.charRecs[(int)text[i] - FONT_FIRST_CHAR].width + spriteFont.charOffsets[(int)text[i] - FONT_FIRST_CHAR].x);
if (spriteFont.charAdvanceX[index] != 0) textWidth += spriteFont.charAdvanceX[index];
else textWidth += (spriteFont.charRecs[index].width + spriteFont.charOffsets[index].x);
} }
else else
{ {
@ -492,7 +533,28 @@ void DrawFPS(int posX, int posY)
// Module specific Functions Definition // Module specific Functions Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Load a Image font file (XNA style) static int GetCharIndex(SpriteFont font, int letter)
{
//#define UNORDERED_CHARSET
#if defined(UNORDERED_CHARSET)
int index = 0;
for (int i = 0; i < font.numChars; i++)
{
if (font.charValues[i] == letter)
{
index = i;
break;
}
}
return index;
#else
return (letter - 32);
#endif
}
// Load an Image font file (XNA style)
static SpriteFont LoadImageFont(Image image, Color key, int firstChar) static SpriteFont LoadImageFont(Image image, Color key, int firstChar)
{ {
#define COLOR_EQUAL(col1, col2) ((col1.r == col2.r)&&(col1.g == col2.g)&&(col1.b == col2.b)&&(col1.a == col2.a)) #define COLOR_EQUAL(col1, col2) ((col1.r == col2.r)&&(col1.g == col2.g)&&(col1.b == col2.b)&&(col1.a == col2.a))
@ -503,8 +565,8 @@ static SpriteFont LoadImageFont(Image image, Color key, int firstChar)
int x = 0; int x = 0;
int y = 0; int y = 0;
// Default number of characters expected supported // Default number of characters supported
#define MAX_FONTCHARS 128 #define MAX_FONTCHARS 256
// We allocate a temporal arrays for chars data measures, // We allocate a temporal arrays for chars data measures,
// once we get the actual number of chars, we copy data to a sized arrays // once we get the actual number of chars, we copy data to a sized arrays
@ -565,15 +627,24 @@ static SpriteFont LoadImageFont(Image image, Color key, int firstChar)
xPosToRead = charSpacing; xPosToRead = charSpacing;
} }
free(pixels);
TraceLog(DEBUG, "SpriteFont data parsed correctly from image"); TraceLog(DEBUG, "SpriteFont data parsed correctly from image");
// NOTE: We need to remove key color borders from image to avoid weird
// artifacts on texture scaling when using FILTER_BILINEAR or FILTER_TRILINEAR
for (int i = 0; i < image.height*image.width; i++) if (COLOR_EQUAL(pixels[i], key)) pixels[i] = BLANK;
// Create a new image with the processed color data (key color replaced by BLANK)
Image fontClear = LoadImageEx(pixels, image.width, image.height);
free(pixels); // Free pixels array memory
// Create spritefont with all data parsed from image // Create spritefont with all data parsed from image
SpriteFont spriteFont = { 0 }; SpriteFont spriteFont = { 0 };
spriteFont.texture = LoadTextureFromImage(image); // Convert loaded image to OpenGL texture spriteFont.texture = LoadTextureFromImage(fontClear); // Convert processed image to OpenGL texture
spriteFont.numChars = index; spriteFont.numChars = index;
UnloadImage(fontClear); // Unload processed image once converted to texture
// We got tempCharValues and tempCharsRecs populated with chars data // We got tempCharValues and tempCharsRecs populated with chars data
// Now we move temp data to sized charValues and charRecs arrays // Now we move temp data to sized charValues and charRecs arrays
@ -803,8 +874,13 @@ static SpriteFont LoadBMFont(const char *fileName)
strncat(texPath, texFileName, strlen(texFileName)); strncat(texPath, texFileName, strlen(texFileName));
TraceLog(DEBUG, "[%s] Font texture loading path: %s", fileName, texPath); TraceLog(DEBUG, "[%s] Font texture loading path: %s", fileName, texPath);
Image imFont = LoadImage(texPath);
font.texture = LoadTexture(texPath); if (imFont.format == UNCOMPRESSED_GRAYSCALE) ImageAlphaMask(&imFont, imFont);
font.texture = LoadTextureFromImage(imFont);
font.size = fontSize; font.size = fontSize;
font.numChars = numChars; font.numChars = numChars;
font.charValues = (int *)malloc(numChars*sizeof(int)); font.charValues = (int *)malloc(numChars*sizeof(int));
@ -812,22 +888,18 @@ static SpriteFont LoadBMFont(const char *fileName)
font.charOffsets = (Vector2 *)malloc(numChars*sizeof(Vector2)); font.charOffsets = (Vector2 *)malloc(numChars*sizeof(Vector2));
font.charAdvanceX = (int *)malloc(numChars*sizeof(int)); font.charAdvanceX = (int *)malloc(numChars*sizeof(int));
UnloadImage(imFont);
free(texPath); free(texPath);
int charId, charX, charY, charWidth, charHeight, charOffsetX, charOffsetY, charAdvanceX; int charId, charX, charY, charWidth, charHeight, charOffsetX, charOffsetY, charAdvanceX;
bool unorderedChars = false;
int firstChar = 0;
for (int i = 0; i < numChars; i++) for (int i = 0; i < numChars; i++)
{ {
fgets(buffer, MAX_BUFFER_SIZE, fntFile); fgets(buffer, MAX_BUFFER_SIZE, fntFile);
sscanf(buffer, "char id=%i x=%i y=%i width=%i height=%i xoffset=%i yoffset=%i xadvance=%i", sscanf(buffer, "char id=%i x=%i y=%i width=%i height=%i xoffset=%i yoffset=%i xadvance=%i",
&charId, &charX, &charY, &charWidth, &charHeight, &charOffsetX, &charOffsetY, &charAdvanceX); &charId, &charX, &charY, &charWidth, &charHeight, &charOffsetX, &charOffsetY, &charAdvanceX);
if (i == 0) firstChar = charId;
else if (i != (charId - firstChar)) unorderedChars = true;
// Save data properly in sprite font // Save data properly in sprite font
font.charValues[i] = charId; font.charValues[i] = charId;
font.charRecs[i] = (Rectangle){ charX, charY, charWidth, charHeight }; font.charRecs[i] = (Rectangle){ charX, charY, charWidth, charHeight };
@ -837,11 +909,7 @@ static SpriteFont LoadBMFont(const char *fileName)
fclose(fntFile); fclose(fntFile);
if (firstChar != FONT_FIRST_CHAR) TraceLog(WARNING, "BMFont not supported: expected SPACE(32) as first character, falling back to default font"); if (font.texture.id == 0)
else if (unorderedChars) TraceLog(WARNING, "BMFont not supported: unordered chars data, falling back to default font");
// NOTE: Font data could be not ordered by charId: 32,33,34,35... raylib does not support unordered BMFonts
if ((firstChar != FONT_FIRST_CHAR) || (unorderedChars) || (font.texture.id == 0))
{ {
UnloadSpriteFont(font); UnloadSpriteFont(font);
font = GetDefaultFont(); font = GetDefaultFont();
@ -853,14 +921,17 @@ static SpriteFont LoadBMFont(const char *fileName)
// Generate a sprite font from TTF file data (font size required) // Generate a sprite font from TTF file data (font size required)
// TODO: Review texture packing method and generation (use oversampling) // TODO: Review texture packing method and generation (use oversampling)
static SpriteFont LoadTTF(const char *fileName, int fontSize, int firstChar, int numChars) static SpriteFont LoadTTF(const char *fileName, int fontSize, int numChars, int *fontChars)
{ {
// NOTE: Generated font uses some hardcoded values // NOTE: Font texture size is predicted (being as much conservative as possible)
#define FONT_TEXTURE_WIDTH 512 // Font texture width // Predictive method consist of supposing same number of chars by line-column (sqrtf)
#define FONT_TEXTURE_HEIGHT 512 // Font texture height // and a maximum character width of 3/4 of fontSize... it worked ok with all my tests...
int textureSize = GetNextPOT(ceil((float)fontSize*3/4)*ceil(sqrtf((float)numChars)));
TraceLog(INFO, "TTF spritefont loading: Predicted texture size: %ix%i", textureSize, textureSize);
unsigned char *ttfBuffer = (unsigned char *)malloc(1 << 25); unsigned char *ttfBuffer = (unsigned char *)malloc(1 << 25);
unsigned char *dataBitmap = (unsigned char *)malloc(FONT_TEXTURE_WIDTH*FONT_TEXTURE_HEIGHT*sizeof(unsigned char)); // One channel bitmap returned! unsigned char *dataBitmap = (unsigned char *)malloc(textureSize*textureSize*sizeof(unsigned char)); // One channel bitmap returned!
stbtt_bakedchar *charData = (stbtt_bakedchar *)malloc(sizeof(stbtt_bakedchar)*numChars); stbtt_bakedchar *charData = (stbtt_bakedchar *)malloc(sizeof(stbtt_bakedchar)*numChars);
SpriteFont font = { 0 }; SpriteFont font = { 0 };
@ -869,40 +940,47 @@ static SpriteFont LoadTTF(const char *fileName, int fontSize, int firstChar, int
if (ttfFile == NULL) if (ttfFile == NULL)
{ {
TraceLog(WARNING, "[%s] FNT file could not be opened", fileName); TraceLog(WARNING, "[%s] TTF file could not be opened", fileName);
return font; return font;
} }
fread(ttfBuffer, 1, 1<<25, ttfFile); fread(ttfBuffer, 1, 1<<25, ttfFile);
if (fontChars[0] != 32) TraceLog(WARNING, "TTF spritefont loading: first character is not SPACE(32) character");
// NOTE: Using stb_truetype crappy packing method, no guarante the font fits the image... // NOTE: Using stb_truetype crappy packing method, no guarante the font fits the image...
stbtt_BakeFontBitmap(ttfBuffer,0, fontSize, dataBitmap, FONT_TEXTURE_WIDTH, FONT_TEXTURE_HEIGHT, firstChar, numChars, charData); // TODO: Replace this function by a proper packing method and support random chars order,
// we already receive a list (fontChars) with the ordered expected characters
int result = stbtt_BakeFontBitmap(ttfBuffer, 0, fontSize, dataBitmap, textureSize, textureSize, fontChars[0], numChars, charData);
//if (result > 0) TraceLog(INFO, "TTF spritefont loading: first unused row of generated bitmap: %i", result);
if (result < 0) TraceLog(WARNING, "TTF spritefont loading: Not all the characters fit in the font");
free(ttfBuffer); free(ttfBuffer);
// Convert image data from grayscale to to UNCOMPRESSED_GRAY_ALPHA // Convert image data from grayscale to to UNCOMPRESSED_GRAY_ALPHA
unsigned char *dataGrayAlpha = (unsigned char *)malloc(FONT_TEXTURE_WIDTH*FONT_TEXTURE_HEIGHT*sizeof(unsigned char)*2); // Two channels unsigned char *dataGrayAlpha = (unsigned char *)malloc(textureSize*textureSize*sizeof(unsigned char)*2); // Two channels
int k = 0;
for (int i = 0; i < FONT_TEXTURE_WIDTH*FONT_TEXTURE_HEIGHT; i++) for (int i = 0, k = 0; i < textureSize*textureSize; i++, k += 2)
{ {
dataGrayAlpha[k] = 255; dataGrayAlpha[k] = 255;
dataGrayAlpha[k + 1] = dataBitmap[i]; dataGrayAlpha[k + 1] = dataBitmap[i];
k += 2;
} }
free(dataBitmap); free(dataBitmap);
// Sprite font generation from TTF extracted data // Sprite font generation from TTF extracted data
Image image; Image image;
image.width = FONT_TEXTURE_WIDTH; image.width = textureSize;
image.height = FONT_TEXTURE_HEIGHT; image.height = textureSize;
image.mipmaps = 1; image.mipmaps = 1;
image.format = UNCOMPRESSED_GRAY_ALPHA; image.format = UNCOMPRESSED_GRAY_ALPHA;
image.data = dataGrayAlpha; image.data = dataGrayAlpha;
font.texture = LoadTextureFromImage(image); font.texture = LoadTextureFromImage(image);
//WritePNG("generated_ttf_image.png", (unsigned char *)image.data, image.width, image.height, 2);
UnloadImage(image); // Unloads dataGrayAlpha UnloadImage(image); // Unloads dataGrayAlpha
font.size = fontSize; font.size = fontSize;
@ -914,7 +992,7 @@ static SpriteFont LoadTTF(const char *fileName, int fontSize, int firstChar, int
for (int i = 0; i < font.numChars; i++) for (int i = 0; i < font.numChars; i++)
{ {
font.charValues[i] = i + firstChar; font.charValues[i] = fontChars[i];
font.charRecs[i].x = (int)charData[i].x0; font.charRecs[i].x = (int)charData[i].x0;
font.charRecs[i].y = (int)charData[i].y0; font.charRecs[i].y = (int)charData[i].y0;

View File

@ -8,7 +8,7 @@
* stb_image - Multiple formats image loading (JPEG, PNG, BMP, TGA, PSD, GIF, PIC) * stb_image - Multiple formats image loading (JPEG, PNG, BMP, TGA, PSD, GIF, PIC)
* NOTE: stb_image has been slightly modified, original library: https://github.com/nothings/stb * NOTE: stb_image has been slightly modified, original library: https://github.com/nothings/stb
* *
* Copyright (c) 2014 Ramon Santamaria (@raysan5) * Copyright (c) 2014-2016 Ramon Santamaria (@raysan5)
* *
* This software is provided "as-is", without any express or implied warranty. In no event * This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software. * will the authors be held liable for any damages arising from the use of this software.
@ -229,7 +229,7 @@ Image LoadImageRaw(const char *fileName, int width, int height, int format, int
// TODO: Review function to support multiple color modes // TODO: Review function to support multiple color modes
Image LoadImageFromRES(const char *rresName, int resId) Image LoadImageFromRES(const char *rresName, int resId)
{ {
Image image; Image image = { 0 };
bool found = false; bool found = false;
char id[4]; // rRES file identifier char id[4]; // rRES file identifier
@ -442,6 +442,96 @@ void UnloadRenderTexture(RenderTexture2D target)
if (target.id != 0) rlDeleteRenderTextures(target); if (target.id != 0) rlDeleteRenderTextures(target);
} }
// Set texture scaling filter mode
void SetTextureFilter(Texture2D texture, int filterMode)
{
switch (filterMode)
{
case FILTER_POINT:
{
if (texture.mipmaps > 1)
{
// RL_FILTER_MIP_NEAREST - tex filter: POINT, mipmaps filter: POINT (sharp switching between mipmaps)
rlTextureParameters(texture.id, RL_TEXTURE_MIN_FILTER, RL_FILTER_MIP_NEAREST);
// RL_FILTER_NEAREST - tex filter: POINT (no filter), no mipmaps
rlTextureParameters(texture.id, RL_TEXTURE_MAG_FILTER, RL_FILTER_NEAREST);
}
else
{
// RL_FILTER_NEAREST - tex filter: POINT (no filter), no mipmaps
rlTextureParameters(texture.id, RL_TEXTURE_MIN_FILTER, RL_FILTER_NEAREST);
rlTextureParameters(texture.id, RL_TEXTURE_MAG_FILTER, RL_FILTER_NEAREST);
}
} break;
case FILTER_BILINEAR:
{
if (texture.mipmaps > 1)
{
// RL_FILTER_LINEAR_MIP_NEAREST - tex filter: BILINEAR, mipmaps filter: POINT (sharp switching between mipmaps)
// Alternative: RL_FILTER_NEAREST_MIP_LINEAR - tex filter: POINT, mipmaps filter: BILINEAR (smooth transition between mipmaps)
rlTextureParameters(texture.id, RL_TEXTURE_MIN_FILTER, RL_FILTER_LINEAR_MIP_NEAREST);
// RL_FILTER_LINEAR - tex filter: BILINEAR, no mipmaps
rlTextureParameters(texture.id, RL_TEXTURE_MAG_FILTER, RL_FILTER_LINEAR);
}
else
{
// RL_FILTER_LINEAR - tex filter: BILINEAR, no mipmaps
rlTextureParameters(texture.id, RL_TEXTURE_MIN_FILTER, RL_FILTER_LINEAR);
rlTextureParameters(texture.id, RL_TEXTURE_MAG_FILTER, RL_FILTER_LINEAR);
}
} break;
case FILTER_TRILINEAR:
{
if (texture.mipmaps > 1)
{
// RL_FILTER_MIP_LINEAR - tex filter: BILINEAR, mipmaps filter: BILINEAR (smooth transition between mipmaps)
rlTextureParameters(texture.id, RL_TEXTURE_MIN_FILTER, RL_FILTER_MIP_LINEAR);
// RL_FILTER_LINEAR - tex filter: BILINEAR, no mipmaps
rlTextureParameters(texture.id, RL_TEXTURE_MAG_FILTER, RL_FILTER_LINEAR);
}
else
{
TraceLog(WARNING, "[TEX ID %i] No mipmaps available for TRILINEAR texture filtering", texture.id);
// RL_FILTER_LINEAR - tex filter: BILINEAR, no mipmaps
rlTextureParameters(texture.id, RL_TEXTURE_MIN_FILTER, RL_FILTER_LINEAR);
rlTextureParameters(texture.id, RL_TEXTURE_MAG_FILTER, RL_FILTER_LINEAR);
}
} break;
case FILTER_ANISOTROPIC_4X: rlTextureParameters(texture.id, RL_TEXTURE_ANISOTROPIC_FILTER, 4); break;
case FILTER_ANISOTROPIC_8X: rlTextureParameters(texture.id, RL_TEXTURE_ANISOTROPIC_FILTER, 8); break;
case FILTER_ANISOTROPIC_16X: rlTextureParameters(texture.id, RL_TEXTURE_ANISOTROPIC_FILTER, 16); break;
default: break;
}
}
// Set texture wrapping mode
void SetTextureWrap(Texture2D texture, int wrapMode)
{
switch (wrapMode)
{
case WRAP_REPEAT:
{
rlTextureParameters(texture.id, RL_TEXTURE_WRAP_S, RL_WRAP_REPEAT);
rlTextureParameters(texture.id, RL_TEXTURE_WRAP_T, RL_WRAP_REPEAT);
} break;
case WRAP_CLAMP:
{
rlTextureParameters(texture.id, RL_TEXTURE_WRAP_S, RL_WRAP_CLAMP);
rlTextureParameters(texture.id, RL_TEXTURE_WRAP_T, RL_WRAP_CLAMP);
} break;
case WRAP_MIRROR:
{
rlTextureParameters(texture.id, RL_TEXTURE_WRAP_S, RL_WRAP_CLAMP_MIRROR);
rlTextureParameters(texture.id, RL_TEXTURE_WRAP_T, RL_WRAP_CLAMP_MIRROR);
} break;
default: break;
}
}
// Get pixel data from image in the form of Color struct array // Get pixel data from image in the form of Color struct array
Color *GetImageData(Image image) Color *GetImageData(Image image)
{ {
@ -694,28 +784,45 @@ void ImageFormat(Image *image, int newFormat)
} }
// Apply alpha mask to image // Apply alpha mask to image
// NOTE 1: Returned image is RGBA - 32bit // NOTE 1: Returned image is GRAY_ALPHA (16bit) or RGBA (32bit)
// NOTE 2: alphaMask should be same size as image // NOTE 2: alphaMask should be same size as image
void ImageAlphaMask(Image *image, Image alphaMask) void ImageAlphaMask(Image *image, Image alphaMask)
{ {
if (image->format >= COMPRESSED_DXT1_RGB) if ((image->width != alphaMask.width) || (image->height != alphaMask.height))
{
TraceLog(WARNING, "Alpha mask must be same size as image");
}
else if (image->format >= COMPRESSED_DXT1_RGB)
{ {
TraceLog(WARNING, "Alpha mask can not be applied to compressed data formats"); TraceLog(WARNING, "Alpha mask can not be applied to compressed data formats");
return;
} }
else else
{ {
// Force mask to be Grayscale // Force mask to be Grayscale
Image mask = ImageCopy(alphaMask); Image mask = ImageCopy(alphaMask);
ImageFormat(&mask, UNCOMPRESSED_GRAYSCALE); if (mask.format != UNCOMPRESSED_GRAYSCALE) ImageFormat(&mask, UNCOMPRESSED_GRAYSCALE);
// Convert image to RGBA // In case image is only grayscale, we just add alpha channel
if (image->format != UNCOMPRESSED_R8G8B8A8) ImageFormat(image, UNCOMPRESSED_R8G8B8A8); if (image->format == UNCOMPRESSED_GRAYSCALE)
// Apply alpha mask to alpha channel
for (int i = 0, k = 3; (i < mask.width*mask.height) || (i < image->width*image->height); i++, k += 4)
{ {
((unsigned char *)image->data)[k] = ((unsigned char *)mask.data)[i]; ImageFormat(image, UNCOMPRESSED_GRAY_ALPHA);
// Apply alpha mask to alpha channel
for (int i = 0, k = 1; (i < mask.width*mask.height) || (i < image->width*image->height); i++, k += 2)
{
((unsigned char *)image->data)[k] = ((unsigned char *)mask.data)[i];
}
}
else
{
// Convert image to RGBA
if (image->format != UNCOMPRESSED_R8G8B8A8) ImageFormat(image, UNCOMPRESSED_R8G8B8A8);
// Apply alpha mask to alpha channel
for (int i = 0, k = 3; (i < mask.width*mask.height) || (i < image->width*image->height); i++, k += 4)
{
((unsigned char *)image->data)[k] = ((unsigned char *)mask.data)[i];
}
} }
UnloadImage(mask); UnloadImage(mask);
@ -1118,7 +1225,7 @@ Image ImageText(const char *text, int fontSize, Color color)
if (fontSize < defaultFontSize) fontSize = defaultFontSize; if (fontSize < defaultFontSize) fontSize = defaultFontSize;
int spacing = fontSize/defaultFontSize; int spacing = fontSize/defaultFontSize;
Image imText = ImageTextEx(GetDefaultFont(), text, fontSize, spacing, color); Image imText = ImageTextEx(GetDefaultFont(), text, (float)fontSize, spacing, color);
return imText; return imText;
} }
@ -1134,7 +1241,7 @@ Image ImageTextEx(SpriteFont font, const char *text, float fontSize, int spacing
// NOTE: GetTextureData() not available in OpenGL ES // NOTE: GetTextureData() not available in OpenGL ES
Image imFont = GetTextureData(font.texture); Image imFont = GetTextureData(font.texture);
ImageFormat(&imFont, UNCOMPRESSED_R8G8B8A8); // Required for color tint ImageFormat(&imFont, UNCOMPRESSED_R8G8B8A8); // Convert to 32 bit for color tint
ImageColorTint(&imFont, tint); // Apply color tint to font ImageColorTint(&imFont, tint); // Apply color tint to font
Color *fontPixels = GetImageData(imFont); Color *fontPixels = GetImageData(imFont);
@ -1183,7 +1290,7 @@ Image ImageTextEx(SpriteFont font, const char *text, float fontSize, int spacing
void ImageDrawText(Image *dst, Vector2 position, const char *text, int fontSize, Color color) void ImageDrawText(Image *dst, Vector2 position, const char *text, int fontSize, Color color)
{ {
// NOTE: For default font, sapcing is set to desired font size / default font size (10) // NOTE: For default font, sapcing is set to desired font size / default font size (10)
ImageDrawTextEx(dst, position, GetDefaultFont(), text, fontSize, fontSize/10, color); ImageDrawTextEx(dst, position, GetDefaultFont(), text, (float)fontSize, fontSize/10, color);
} }
// Draw text (custom sprite font) within an image (destination) // Draw text (custom sprite font) within an image (destination)
@ -1317,7 +1424,7 @@ void ImageColorContrast(Image *image, float contrast)
if (contrast < -100) contrast = -100; if (contrast < -100) contrast = -100;
if (contrast > 100) contrast = 100; if (contrast > 100) contrast = 100;
contrast = (100.0 + contrast)/100.0; contrast = (100.0f + contrast)/100.0f;
contrast *= contrast; contrast *= contrast;
Color *pixels = GetImageData(*image); Color *pixels = GetImageData(*image);
@ -1326,7 +1433,7 @@ void ImageColorContrast(Image *image, float contrast)
{ {
for (int x = 0; x < image->width; x++) for (int x = 0; x < image->width; x++)
{ {
float pR = (float)pixels[y*image->width + x].r/255.0; float pR = (float)pixels[y*image->width + x].r/255.0f;
pR -= 0.5; pR -= 0.5;
pR *= contrast; pR *= contrast;
pR += 0.5; pR += 0.5;
@ -1334,7 +1441,7 @@ void ImageColorContrast(Image *image, float contrast)
if (pR < 0) pR = 0; if (pR < 0) pR = 0;
if (pR > 255) pR = 255; if (pR > 255) pR = 255;
float pG = (float)pixels[y*image->width + x].g/255.0; float pG = (float)pixels[y*image->width + x].g/255.0f;
pG -= 0.5; pG -= 0.5;
pG *= contrast; pG *= contrast;
pG += 0.5; pG += 0.5;
@ -1342,7 +1449,7 @@ void ImageColorContrast(Image *image, float contrast)
if (pG < 0) pG = 0; if (pG < 0) pG = 0;
if (pG > 255) pG = 255; if (pG > 255) pG = 255;
float pB = (float)pixels[y*image->width + x].b/255.0; float pB = (float)pixels[y*image->width + x].b/255.0f;
pB -= 0.5; pB -= 0.5;
pB *= contrast; pB *= contrast;
pB += 0.5; pB += 0.5;

View File

@ -8,7 +8,7 @@
* tinfl - zlib DEFLATE algorithm decompression lib * tinfl - zlib DEFLATE algorithm decompression lib
* stb_image_write - PNG writting functions * stb_image_write - PNG writting functions
* *
* Copyright (c) 2014 Ramon Santamaria (@raysan5) * Copyright (c) 2014-2016 Ramon Santamaria (@raysan5)
* *
* This software is provided "as-is", without any express or implied warranty. In no event * This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software. * will the authors be held liable for any damages arising from the use of this software.