Added full support for HTML5 (emscripten)
Corrected some bugs on the way... Automatically convert textures to POT on RPI and WEB
This commit is contained in:
parent
08a4ee34eb
commit
905b6ec53d
14 changed files with 527 additions and 234 deletions
49
src/audio.c
49
src/audio.c
|
@ -45,9 +45,14 @@
|
||||||
// Defines and Macros
|
// Defines and Macros
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
#define MUSIC_STREAM_BUFFERS 2
|
#define MUSIC_STREAM_BUFFERS 2
|
||||||
#define MUSIC_BUFFER_SIZE 4096*2 // PCM data buffer (short) - 16Kb
|
|
||||||
// NOTE: Reduced to avoid frame-stalls on RPI
|
#if defined(PLATFORM_RPI)
|
||||||
//#define MUSIC_BUFFER_SIZE 4096*8 // PCM data buffer (short) - 64Kb
|
// NOTE: On RPI should be lower to avoid frame-stalls
|
||||||
|
#define MUSIC_BUFFER_SIZE 4096*2 // PCM data buffer (short) - 16Kb (RPI)
|
||||||
|
#else
|
||||||
|
// NOTE: On HTML5 (emscripten) this is allocated on heap, by default it's only 16MB!...just take care...
|
||||||
|
#define MUSIC_BUFFER_SIZE 4096*8 // PCM data buffer (short) - 64Kb
|
||||||
|
#endif
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Types and Structures Definition
|
// Types and Structures Definition
|
||||||
|
@ -97,7 +102,7 @@ void InitAudioDevice(void)
|
||||||
// Open and initialize a device with default settings
|
// Open and initialize a device with default settings
|
||||||
ALCdevice *device = alcOpenDevice(NULL);
|
ALCdevice *device = alcOpenDevice(NULL);
|
||||||
|
|
||||||
if(!device) TraceLog(ERROR, "Could not open audio device");
|
if(!device) TraceLog(ERROR, "Audio device could not be opened");
|
||||||
|
|
||||||
ALCcontext *context = alcCreateContext(device, NULL);
|
ALCcontext *context = alcCreateContext(device, NULL);
|
||||||
|
|
||||||
|
@ -196,13 +201,12 @@ Sound LoadSound(char *fileName)
|
||||||
|
|
||||||
// Attach sound buffer to source
|
// Attach sound buffer to source
|
||||||
alSourcei(source, AL_BUFFER, buffer);
|
alSourcei(source, AL_BUFFER, buffer);
|
||||||
|
|
||||||
|
TraceLog(INFO, "[%s] Sound file loaded successfully (SampleRate: %i, BitRate: %i, Channels: %i)", fileName, wave.sampleRate, wave.bitsPerSample, wave.channels);
|
||||||
|
|
||||||
// Unallocate WAV data
|
// Unallocate WAV data
|
||||||
UnloadWave(wave);
|
UnloadWave(wave);
|
||||||
|
|
||||||
TraceLog(INFO, "[%s] Sound file loaded successfully", fileName);
|
|
||||||
TraceLog(INFO, "[%s] Sample rate: %i - Channels: %i", fileName, wave.sampleRate, wave.channels);
|
|
||||||
|
|
||||||
sound.source = source;
|
sound.source = source;
|
||||||
sound.buffer = buffer;
|
sound.buffer = buffer;
|
||||||
}
|
}
|
||||||
|
@ -254,8 +258,7 @@ Sound LoadSoundFromWave(Wave wave)
|
||||||
// Unallocate WAV data
|
// Unallocate WAV data
|
||||||
UnloadWave(wave);
|
UnloadWave(wave);
|
||||||
|
|
||||||
TraceLog(INFO, "[Wave] Sound file loaded successfully");
|
TraceLog(INFO, "[Wave] Sound file loaded successfully (SampleRate: %i, BitRate: %i, Channels: %i)", wave.sampleRate, wave.bitsPerSample, wave.channels);
|
||||||
TraceLog(INFO, "[Wave] Sample rate: %i - Channels: %i", wave.sampleRate, wave.channels);
|
|
||||||
|
|
||||||
sound.source = source;
|
sound.source = source;
|
||||||
sound.buffer = buffer;
|
sound.buffer = buffer;
|
||||||
|
@ -280,7 +283,10 @@ Sound LoadSoundFromRES(const char *rresName, int resId)
|
||||||
|
|
||||||
FILE *rresFile = fopen(rresName, "rb");
|
FILE *rresFile = fopen(rresName, "rb");
|
||||||
|
|
||||||
if (!rresFile) TraceLog(WARNING, "[%s] Could not open raylib resource file", rresName);
|
if (rresFile == NULL)
|
||||||
|
{
|
||||||
|
TraceLog(WARNING, "[%s] rRES raylib resource file could not be opened", rresName);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Read rres file (basic file check - id)
|
// Read rres file (basic file check - id)
|
||||||
|
@ -372,12 +378,12 @@ Sound LoadSoundFromRES(const char *rresName, int resId)
|
||||||
|
|
||||||
// Attach sound buffer to source
|
// Attach sound buffer to source
|
||||||
alSourcei(source, AL_BUFFER, buffer);
|
alSourcei(source, AL_BUFFER, buffer);
|
||||||
|
|
||||||
|
TraceLog(INFO, "[%s] Sound loaded successfully from resource (SampleRate: %i, BitRate: %i, Channels: %i)", rresName, wave.sampleRate, wave.bitsPerSample, wave.channels);
|
||||||
|
|
||||||
// Unallocate WAV data
|
// Unallocate WAV data
|
||||||
UnloadWave(wave);
|
UnloadWave(wave);
|
||||||
|
|
||||||
TraceLog(INFO, "[%s] Sound loaded successfully from resource, sample rate: %i", rresName, (int)sampleRate);
|
|
||||||
|
|
||||||
sound.source = source;
|
sound.source = source;
|
||||||
sound.buffer = buffer;
|
sound.buffer = buffer;
|
||||||
}
|
}
|
||||||
|
@ -492,7 +498,10 @@ void PlayMusicStream(char *fileName)
|
||||||
// Open audio stream
|
// Open audio stream
|
||||||
currentMusic.stream = stb_vorbis_open_filename(fileName, NULL, NULL);
|
currentMusic.stream = stb_vorbis_open_filename(fileName, NULL, NULL);
|
||||||
|
|
||||||
if (currentMusic.stream == NULL) TraceLog(WARNING, "[%s] Could not open ogg audio file", fileName);
|
if (currentMusic.stream == NULL)
|
||||||
|
{
|
||||||
|
TraceLog(WARNING, "[%s] OGG audio file could not be opened", fileName);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Get file info
|
// Get file info
|
||||||
|
@ -582,11 +591,13 @@ void ResumeMusicStream(void)
|
||||||
// Check if music is playing
|
// Check if music is playing
|
||||||
bool MusicIsPlaying(void)
|
bool MusicIsPlaying(void)
|
||||||
{
|
{
|
||||||
ALenum state;
|
bool playing = false;
|
||||||
|
ALint state;
|
||||||
|
|
||||||
alGetSourcei(currentMusic.source, AL_SOURCE_STATE, &state);
|
alGetSourcei(currentMusic.source, AL_SOURCE_STATE, &state);
|
||||||
|
if (state == AL_PLAYING) playing = true;
|
||||||
|
|
||||||
return (state == AL_PLAYING);
|
return playing;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set volume for music
|
// Set volume for music
|
||||||
|
@ -757,9 +768,9 @@ static Wave LoadWAV(const char *fileName)
|
||||||
|
|
||||||
wavFile = fopen(fileName, "rb");
|
wavFile = fopen(fileName, "rb");
|
||||||
|
|
||||||
if (!wavFile)
|
if (wavFile == NULL)
|
||||||
{
|
{
|
||||||
TraceLog(WARNING, "[%s] Could not open WAV file", fileName);
|
TraceLog(WARNING, "[%s] WAV file could not be opened", fileName);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -811,7 +822,7 @@ static Wave LoadWAV(const char *fileName)
|
||||||
wave.channels = waveFormat.numChannels;
|
wave.channels = waveFormat.numChannels;
|
||||||
wave.bitsPerSample = waveFormat.bitsPerSample;
|
wave.bitsPerSample = waveFormat.bitsPerSample;
|
||||||
|
|
||||||
TraceLog(INFO, "[%s] Wave file loaded successfully", fileName);
|
TraceLog(INFO, "[%s] WAV file loaded successfully (SampleRate: %i, BitRate: %i, Channels: %i)", fileName, wave.sampleRate, wave.bitsPerSample, wave.channels);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -860,6 +871,8 @@ static Wave LoadOGG(char *fileName)
|
||||||
int samplesObtained = stb_vorbis_get_samples_short_interleaved(oggFile, info.channels, wave.data, totalSamplesLength);
|
int samplesObtained = stb_vorbis_get_samples_short_interleaved(oggFile, info.channels, wave.data, totalSamplesLength);
|
||||||
|
|
||||||
TraceLog(DEBUG, "[%s] Samples obtained: %i", fileName, samplesObtained);
|
TraceLog(DEBUG, "[%s] Samples obtained: %i", fileName, samplesObtained);
|
||||||
|
|
||||||
|
TraceLog(INFO, "[%s] OGG file loaded successfully (SampleRate: %i, BitRate: %i, Channels: %i)", fileName, wave.sampleRate, wave.bitsPerSample, wave.channels);
|
||||||
|
|
||||||
stb_vorbis_close(oggFile);
|
stb_vorbis_close(oggFile);
|
||||||
|
|
||||||
|
|
251
src/core.c
251
src/core.c
|
@ -92,7 +92,7 @@
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Defines and Macros
|
// Defines and Macros
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// ...
|
#define MAX_TOUCH_POINTS 256
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Types and Structures Definition
|
// Types and Structures Definition
|
||||||
|
@ -112,7 +112,14 @@ static bool windowReady = false; // Used to detect display initia
|
||||||
|
|
||||||
// Gestures detection variables
|
// Gestures detection variables
|
||||||
static float tapTouchX, tapTouchY;
|
static float tapTouchX, tapTouchY;
|
||||||
|
static int64_t lastTapTime = 0;
|
||||||
|
static float lastTapX = 0, lastTapY = 0;
|
||||||
static bool touchTap = false;
|
static bool touchTap = false;
|
||||||
|
static bool doubleTap = false;
|
||||||
|
static bool drag = false;
|
||||||
|
static int stdVector[MAX_TOUCH_POINTS];
|
||||||
|
static int indexPosition = 0;
|
||||||
|
const AInputEvent* eventDrag;
|
||||||
static int32_t touchId;
|
static int32_t touchId;
|
||||||
const int32_t DOUBLE_TAP_TIMEOUT = 300*1000000;
|
const int32_t DOUBLE_TAP_TIMEOUT = 300*1000000;
|
||||||
const int32_t DOUBLE_TAP_SLOP = 100;
|
const int32_t DOUBLE_TAP_SLOP = 100;
|
||||||
|
@ -184,6 +191,7 @@ static int previousMouseWheelY = 0; // Required to track mouse wheel var
|
||||||
static int currentMouseWheelY = 0; // Required to track mouse wheel variation
|
static int currentMouseWheelY = 0; // Required to track mouse wheel variation
|
||||||
|
|
||||||
static int exitKey = KEY_ESCAPE; // Default exit key (ESC)
|
static int exitKey = KEY_ESCAPE; // Default exit key (ESC)
|
||||||
|
static int lastKeyPressed = -1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(PLATFORM_ANDROID)
|
#if defined(PLATFORM_ANDROID)
|
||||||
|
@ -230,6 +238,8 @@ static void InitGamepad(void); // Init raw gamepad inpu
|
||||||
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
|
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
|
||||||
static void ErrorCallback(int error, const char *description); // GLFW3 Error Callback, runs on GLFW3 error
|
static void ErrorCallback(int error, const char *description); // GLFW3 Error Callback, runs on GLFW3 error
|
||||||
static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods); // GLFW3 Keyboard Callback, runs on key pressed
|
static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods); // GLFW3 Keyboard Callback, runs on key pressed
|
||||||
|
static void MouseButtonCallback(GLFWwindow *window, int button, int action, int mods); // GLFW3 Mouse Button Callback, runs on mouse button pressed
|
||||||
|
static void CharCallback(GLFWwindow *window, unsigned int key); // GLFW3 Char Key Callback, runs on key pressed (get char value)
|
||||||
static void ScrollCallback(GLFWwindow *window, double xoffset, double yoffset); // GLFW3 Srolling Callback, runs on mouse wheel
|
static void ScrollCallback(GLFWwindow *window, double xoffset, double yoffset); // GLFW3 Srolling Callback, runs on mouse wheel
|
||||||
static void CursorEnterCallback(GLFWwindow *window, int enter); // GLFW3 Cursor Enter Callback, cursor enters client area
|
static void CursorEnterCallback(GLFWwindow *window, int enter); // GLFW3 Cursor Enter Callback, cursor enters client area
|
||||||
static void WindowSizeCallback(GLFWwindow *window, int width, int height); // GLFW3 WindowSize Callback, runs when window is resized
|
static void WindowSizeCallback(GLFWwindow *window, int width, int height); // GLFW3 WindowSize Callback, runs when window is resized
|
||||||
|
@ -441,6 +451,12 @@ int GetScreenHeight(void)
|
||||||
return screenHeight;
|
return screenHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the last key pressed
|
||||||
|
int GetKeyPressed(void)
|
||||||
|
{
|
||||||
|
return lastKeyPressed;
|
||||||
|
}
|
||||||
|
|
||||||
// Sets Background Color
|
// Sets Background Color
|
||||||
void ClearBackground(Color color)
|
void ClearBackground(Color color)
|
||||||
{
|
{
|
||||||
|
@ -623,13 +639,7 @@ bool IsKeyPressed(int key)
|
||||||
{
|
{
|
||||||
bool pressed = false;
|
bool pressed = false;
|
||||||
|
|
||||||
currentKeyState[key] = IsKeyDown(key);
|
if ((currentKeyState[key] != previousKeyState[key]) && (currentKeyState[key] == 1)) pressed = true;
|
||||||
|
|
||||||
if (currentKeyState[key] != previousKeyState[key])
|
|
||||||
{
|
|
||||||
if (currentKeyState[key]) pressed = true;
|
|
||||||
previousKeyState[key] = currentKeyState[key];
|
|
||||||
}
|
|
||||||
else pressed = false;
|
else pressed = false;
|
||||||
|
|
||||||
return pressed;
|
return pressed;
|
||||||
|
@ -647,13 +657,7 @@ bool IsKeyReleased(int key)
|
||||||
{
|
{
|
||||||
bool released = false;
|
bool released = false;
|
||||||
|
|
||||||
currentKeyState[key] = IsKeyUp(key);
|
if ((currentKeyState[key] != previousKeyState[key]) && (currentKeyState[key] == 0)) released = true;
|
||||||
|
|
||||||
if (currentKeyState[key] != previousKeyState[key])
|
|
||||||
{
|
|
||||||
if (currentKeyState[key]) released = true;
|
|
||||||
previousKeyState[key] = currentKeyState[key];
|
|
||||||
}
|
|
||||||
else released = false;
|
else released = false;
|
||||||
|
|
||||||
return released;
|
return released;
|
||||||
|
@ -671,13 +675,7 @@ bool IsMouseButtonPressed(int button)
|
||||||
{
|
{
|
||||||
bool pressed = false;
|
bool pressed = false;
|
||||||
|
|
||||||
currentMouseState[button] = IsMouseButtonDown(button);
|
if ((currentMouseState[button] != previousMouseState[button]) && (currentMouseState[button] == 1)) pressed = true;
|
||||||
|
|
||||||
if (currentMouseState[button] != previousMouseState[button])
|
|
||||||
{
|
|
||||||
if (currentMouseState[button]) pressed = true;
|
|
||||||
previousMouseState[button] = currentMouseState[button];
|
|
||||||
}
|
|
||||||
else pressed = false;
|
else pressed = false;
|
||||||
|
|
||||||
return pressed;
|
return pressed;
|
||||||
|
@ -695,13 +693,7 @@ bool IsMouseButtonReleased(int button)
|
||||||
{
|
{
|
||||||
bool released = false;
|
bool released = false;
|
||||||
|
|
||||||
currentMouseState[button] = IsMouseButtonUp(button);
|
if ((currentMouseState[button] != previousMouseState[button]) && (currentMouseState[button] == 0)) released = true;
|
||||||
|
|
||||||
if (currentMouseState[button] != previousMouseState[button])
|
|
||||||
{
|
|
||||||
if (currentMouseState[button]) released = true;
|
|
||||||
previousMouseState[button] = currentMouseState[button];
|
|
||||||
}
|
|
||||||
else released = false;
|
else released = false;
|
||||||
|
|
||||||
return released;
|
return released;
|
||||||
|
@ -858,6 +850,18 @@ bool IsScreenTouched(void)
|
||||||
return touchTap;
|
return touchTap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsDoubleTap(void)
|
||||||
|
{
|
||||||
|
if (doubleTap) TraceLog(INFO, "DOUBLE TAP gesture detected");
|
||||||
|
|
||||||
|
return doubleTap;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsDragGesture(void)
|
||||||
|
{
|
||||||
|
return drag;
|
||||||
|
}
|
||||||
|
|
||||||
// Returns touch position X
|
// Returns touch position X
|
||||||
int GetTouchX(void)
|
int GetTouchX(void)
|
||||||
{
|
{
|
||||||
|
@ -877,6 +881,27 @@ Vector2 GetTouchPosition(void)
|
||||||
|
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*bool GetPointer(Vector2 *dragPositions)
|
||||||
|
{
|
||||||
|
//static int stdVector[MAX_TOUCH_POINTS];
|
||||||
|
//static int indexPosition = 0;
|
||||||
|
//if (indexPosition == 0) return false;
|
||||||
|
Vector2 vec_pointers_[];
|
||||||
|
|
||||||
|
//eventDrag
|
||||||
|
int32_t iIndex = FindIndex( eventDrag, vec_pointers_[0] );
|
||||||
|
|
||||||
|
if (iIndex == -1) return false;
|
||||||
|
|
||||||
|
float x = AMotionEvent_getX(eventDrag, iIndex);
|
||||||
|
float y = AMotionEvent_getY(eventDrag, iIndex);
|
||||||
|
|
||||||
|
*dragPositions = Vector2( x, y );
|
||||||
|
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}*/
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
@ -977,6 +1002,8 @@ static void InitDisplay(int width, int height)
|
||||||
glfwSetWindowSizeCallback(window, WindowSizeCallback);
|
glfwSetWindowSizeCallback(window, WindowSizeCallback);
|
||||||
glfwSetCursorEnterCallback(window, CursorEnterCallback);
|
glfwSetCursorEnterCallback(window, CursorEnterCallback);
|
||||||
glfwSetKeyCallback(window, KeyCallback);
|
glfwSetKeyCallback(window, KeyCallback);
|
||||||
|
glfwSetMouseButtonCallback(window, MouseButtonCallback);
|
||||||
|
glfwSetCharCallback(window, CharCallback);
|
||||||
glfwSetScrollCallback(window, ScrollCallback);
|
glfwSetScrollCallback(window, ScrollCallback);
|
||||||
|
|
||||||
glfwMakeContextCurrent(window);
|
glfwMakeContextCurrent(window);
|
||||||
|
@ -1168,6 +1195,25 @@ static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, i
|
||||||
TakeScreenshot();
|
TakeScreenshot();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
else currentKeyState[key] = action;
|
||||||
|
|
||||||
|
// HACK for GuiTextBox, to deteck back key
|
||||||
|
// TODO: Review...
|
||||||
|
if ((key == 259) && (action == GLFW_PRESS)) lastKeyPressed = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GLFW3 Mouse Button Callback, runs on mouse button pressed
|
||||||
|
static void MouseButtonCallback(GLFWwindow *window, int button, int action, int mods)
|
||||||
|
{
|
||||||
|
currentMouseState[button] = action;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GLFW3 Char Key Callback, runs on key pressed (get char value)
|
||||||
|
static void CharCallback(GLFWwindow *window, unsigned int key)
|
||||||
|
{
|
||||||
|
lastKeyPressed = key;
|
||||||
|
|
||||||
|
//TraceLog(INFO, "Char Callback Key pressed: %i\n", key);
|
||||||
}
|
}
|
||||||
|
|
||||||
// GLFW3 CursorEnter Callback, when cursor enters the window
|
// GLFW3 CursorEnter Callback, when cursor enters the window
|
||||||
|
@ -1203,6 +1249,7 @@ static int32_t InputCallback(struct android_app *app, AInputEvent *event)
|
||||||
|
|
||||||
if (type == AINPUT_EVENT_TYPE_MOTION)
|
if (type == AINPUT_EVENT_TYPE_MOTION)
|
||||||
{
|
{
|
||||||
|
// Detect TOUCH position
|
||||||
if ((screenWidth > displayWidth) || (screenHeight > displayHeight))
|
if ((screenWidth > displayWidth) || (screenHeight > displayHeight))
|
||||||
{
|
{
|
||||||
// TODO: Seems to work ok but... review!
|
// TODO: Seems to work ok but... review!
|
||||||
|
@ -1266,7 +1313,124 @@ static int32_t InputCallback(struct android_app *app, AInputEvent *event)
|
||||||
//size_t pointerCount = AMotionEvent_getPointerCount(event);
|
//size_t pointerCount = AMotionEvent_getPointerCount(event);
|
||||||
//float AMotionEvent_getPressure(const AInputEvent *motion_event, size_t pointer_index); // 0 to 1
|
//float AMotionEvent_getPressure(const AInputEvent *motion_event, size_t pointer_index); // 0 to 1
|
||||||
//float AMotionEvent_getSize(const AInputEvent *motion_event, size_t pointer_index); // Pressed area
|
//float AMotionEvent_getSize(const AInputEvent *motion_event, size_t pointer_index); // Pressed area
|
||||||
|
|
||||||
|
// Detect DOUBLE TAP event
|
||||||
|
bool tapDetected = touchTap;
|
||||||
|
|
||||||
|
switch (flags)
|
||||||
|
{
|
||||||
|
case AMOTION_EVENT_ACTION_DOWN:
|
||||||
|
{
|
||||||
|
int64_t eventTime = AMotionEvent_getEventTime(event);
|
||||||
|
|
||||||
|
if (eventTime - lastTapTime <= DOUBLE_TAP_TIMEOUT)
|
||||||
|
{
|
||||||
|
float x = AMotionEvent_getX(event, 0) - lastTapX;
|
||||||
|
float y = AMotionEvent_getY(event, 0) - lastTapY;
|
||||||
|
|
||||||
|
float densityFactor = 1.0f;
|
||||||
|
|
||||||
|
if ((x*x + y*y) < (DOUBLE_TAP_SLOP*DOUBLE_TAP_SLOP*densityFactor))
|
||||||
|
{
|
||||||
|
// Doubletap detected
|
||||||
|
doubleTap = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case AMOTION_EVENT_ACTION_UP:
|
||||||
|
{
|
||||||
|
if (tapDetected)
|
||||||
|
{
|
||||||
|
lastTapTime = AMotionEvent_getEventTime(event);
|
||||||
|
lastTapX = AMotionEvent_getX(event, 0);
|
||||||
|
lastTapY = AMotionEvent_getY(event, 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Detect DRAG event
|
||||||
|
//int32_t action = AMotionEvent_getAction(event);
|
||||||
|
|
||||||
|
int32_t index = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
|
||||||
|
//uint32_t flags = action & AMOTION_EVENT_ACTION_MASK;
|
||||||
|
//event_ = event;
|
||||||
|
|
||||||
|
int32_t count = AMotionEvent_getPointerCount(event);
|
||||||
|
|
||||||
|
switch (flags)
|
||||||
|
{
|
||||||
|
case AMOTION_EVENT_ACTION_DOWN:
|
||||||
|
{
|
||||||
|
stdVector[indexPosition] = AMotionEvent_getPointerId(event, 0);
|
||||||
|
indexPosition++;
|
||||||
|
TraceLog(INFO, "ACTION_DOWN");
|
||||||
|
|
||||||
|
//ret = GESTURE_STATE_START;
|
||||||
|
} break;
|
||||||
|
case AMOTION_EVENT_ACTION_POINTER_DOWN:
|
||||||
|
{
|
||||||
|
stdVector[indexPosition] = AMotionEvent_getPointerId(event, index);
|
||||||
|
indexPosition++;
|
||||||
|
TraceLog(INFO, "ACTION_POINTER_DOWN");
|
||||||
|
|
||||||
|
} break;
|
||||||
|
case AMOTION_EVENT_ACTION_UP:
|
||||||
|
{
|
||||||
|
//int value = stdVector[indexPosition];
|
||||||
|
indexPosition--;
|
||||||
|
//ret = GESTURE_STATE_END;
|
||||||
|
TraceLog(INFO, "ACTION_UP");
|
||||||
|
|
||||||
|
} break;
|
||||||
|
case AMOTION_EVENT_ACTION_POINTER_UP:
|
||||||
|
{
|
||||||
|
int32_t releasedPointerId = AMotionEvent_getPointerId(event, index);
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for (i = 0; i < MAX_TOUCH_POINTS; i++)
|
||||||
|
{
|
||||||
|
if (stdVector[i] == releasedPointerId)
|
||||||
|
{
|
||||||
|
for (int k = i; k < indexPosition - 1; k++)
|
||||||
|
{
|
||||||
|
stdVector[k] = stdVector[k + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
//indexPosition--;
|
||||||
|
indexPosition = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i <= 1)
|
||||||
|
{
|
||||||
|
// Reset pinch or drag
|
||||||
|
//if (count == 2) //ret = GESTURE_STATE_START;
|
||||||
|
}
|
||||||
|
TraceLog(INFO, "ACTION_POINTER_UP");
|
||||||
|
|
||||||
|
} break;
|
||||||
|
case AMOTION_EVENT_ACTION_MOVE:
|
||||||
|
{
|
||||||
|
if (count == 1)
|
||||||
|
{
|
||||||
|
//TraceLog(INFO, "DRAG gesture detected");
|
||||||
|
|
||||||
|
drag = true; //ret = GESTURE_STATE_MOVE;
|
||||||
|
}
|
||||||
|
else break;
|
||||||
|
TraceLog(INFO, "ACTION_MOVE");
|
||||||
|
|
||||||
|
} break;
|
||||||
|
case AMOTION_EVENT_ACTION_CANCEL: break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else if (type == AINPUT_EVENT_TYPE_KEY)
|
else if (type == AINPUT_EVENT_TYPE_KEY)
|
||||||
|
@ -1467,14 +1631,23 @@ static void PollInputEvents(void)
|
||||||
|
|
||||||
// Keyboard polling
|
// Keyboard polling
|
||||||
// Automatically managed by GLFW3 through callback
|
// Automatically managed by GLFW3 through callback
|
||||||
|
lastKeyPressed = -1;
|
||||||
|
|
||||||
|
// Register previous keys states
|
||||||
|
for (int i = 0; i < 512; i++) previousKeyState[i] = currentKeyState[i];
|
||||||
|
|
||||||
|
// Register previous mouse states
|
||||||
|
for (int i = 0; i < 3; i++) previousMouseState[i] = currentMouseState[i];
|
||||||
|
|
||||||
glfwPollEvents(); // Register keyboard/mouse events
|
glfwPollEvents(); // Register keyboard/mouse events
|
||||||
#elif defined(PLATFORM_ANDROID)
|
#elif defined(PLATFORM_ANDROID)
|
||||||
|
|
||||||
// TODO: Check virtual keyboard (?)
|
// TODO: Check virtual keyboard (?)
|
||||||
|
|
||||||
// Reset touchTap event
|
// Reset touch events
|
||||||
touchTap = false;
|
touchTap = false;
|
||||||
|
doubleTap = false;
|
||||||
|
drag = false;
|
||||||
|
|
||||||
// Poll Events (registered events)
|
// Poll Events (registered events)
|
||||||
while ((ident = ALooper_pollAll(0, NULL, &events,(void**)&source)) >= 0)
|
while ((ident = ALooper_pollAll(0, NULL, &events,(void**)&source)) >= 0)
|
||||||
|
@ -1623,14 +1796,17 @@ static void PollInputEvents(void)
|
||||||
static void InitMouse(void)
|
static void InitMouse(void)
|
||||||
{
|
{
|
||||||
// NOTE: We can use /dev/input/mice to read from all available mice
|
// NOTE: We can use /dev/input/mice to read from all available mice
|
||||||
if ((mouseStream = open(DEFAULT_MOUSE_DEV, O_RDONLY|O_NONBLOCK)) < 0) TraceLog(WARNING, "Could not open mouse device, no mouse available");
|
if ((mouseStream = open(DEFAULT_MOUSE_DEV, O_RDONLY|O_NONBLOCK)) < 0)
|
||||||
|
{
|
||||||
|
TraceLog(WARNING, "Mouse device could not be opened, no mouse available");
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mouseReady = true;
|
mouseReady = true;
|
||||||
|
|
||||||
int err = pthread_create(&mouseThreadId, NULL, &MouseThread, NULL);
|
int error = pthread_create(&mouseThreadId, NULL, &MouseThread, NULL);
|
||||||
|
|
||||||
if (err != 0) TraceLog(WARNING, "Error creating mouse input event thread");
|
if (error != 0) TraceLog(WARNING, "Error creating mouse input event thread");
|
||||||
else TraceLog(INFO, "Mouse device initialized successfully");
|
else TraceLog(INFO, "Mouse device initialized successfully");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1741,7 +1917,7 @@ static void RestoreKeyboard(void)
|
||||||
static void InitGamepad(void)
|
static void InitGamepad(void)
|
||||||
{
|
{
|
||||||
// TODO: Gamepad support
|
// TODO: Gamepad support
|
||||||
if ((gamepadStream = open(DEFAULT_GAMEPAD_DEV, O_RDONLY|O_NONBLOCK)) < 0) TraceLog(WARNING, "Could not open gamepad device, no gamepad available");
|
if ((gamepadStream = open(DEFAULT_GAMEPAD_DEV, O_RDONLY|O_NONBLOCK)) < 0) TraceLog(WARNING, "Gamepad device could not be opened, no gamepad available");
|
||||||
else TraceLog(INFO, "Gamepad device initialized successfully");
|
else TraceLog(INFO, "Gamepad device initialized successfully");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1763,7 +1939,7 @@ static void SetupFramebufferSize(int displayWidth, int displayHeight)
|
||||||
// Calculate renderWidth and renderHeight, we have the display size (input params) and the desired screen size (global var)
|
// Calculate renderWidth and renderHeight, we have the display size (input params) and the desired screen size (global var)
|
||||||
if ((screenWidth > displayWidth) || (screenHeight > displayHeight))
|
if ((screenWidth > displayWidth) || (screenHeight > displayHeight))
|
||||||
{
|
{
|
||||||
TraceLog(WARNING, "DOWNSCALING: Required screen size (%i x %i) is bigger than display size (%i x %i)", screenWidth, screenHeight, displayWidth, displayHeight);
|
TraceLog(WARNING, "DOWNSCALING: Required screen size (%ix%i) is bigger than display size (%ix%i)", screenWidth, screenHeight, displayWidth, displayHeight);
|
||||||
|
|
||||||
// Downscaling to fit display with border-bars
|
// Downscaling to fit display with border-bars
|
||||||
float widthRatio = (float)displayWidth/(float)screenWidth;
|
float widthRatio = (float)displayWidth/(float)screenWidth;
|
||||||
|
@ -1832,6 +2008,7 @@ static void SetupFramebufferSize(int displayWidth, int displayHeight)
|
||||||
// Plays raylib logo appearing animation
|
// Plays raylib logo appearing animation
|
||||||
static void LogoAnimation(void)
|
static void LogoAnimation(void)
|
||||||
{
|
{
|
||||||
|
#ifndef PLATFORM_WEB
|
||||||
int logoPositionX = screenWidth/2 - 128;
|
int logoPositionX = screenWidth/2 - 128;
|
||||||
int logoPositionY = screenHeight/2 - 128;
|
int logoPositionY = screenHeight/2 - 128;
|
||||||
|
|
||||||
|
@ -1949,6 +2126,8 @@ static void LogoAnimation(void)
|
||||||
EndDrawing();
|
EndDrawing();
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
showLogo = false; // Prevent for repeating when reloading window (Android)
|
showLogo = false; // Prevent for repeating when reloading window (Android)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
14
src/makefile
14
src/makefile
|
@ -1,8 +1,6 @@
|
||||||
#**************************************************************************************************
|
#**************************************************************************************************
|
||||||
#
|
#
|
||||||
# raylib for Raspberry Pi and Windows desktop
|
# raylib makefile for desktop platforms, Raspberry Pi and HTML5 (emscripten)
|
||||||
#
|
|
||||||
# makefile for library compilation (raylib.a)
|
|
||||||
#
|
#
|
||||||
# Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
|
# Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
|
||||||
#
|
#
|
||||||
|
@ -23,8 +21,8 @@
|
||||||
#
|
#
|
||||||
#**************************************************************************************************
|
#**************************************************************************************************
|
||||||
|
|
||||||
# define raylib platform (by default, compile for RPI)
|
# define raylib platform to compile for
|
||||||
# Other possible platforms: PLATFORM_DESKTOP_WIN PLATFORM_DESKTOP_LINUX PLATFORM_WEB
|
# possible platforms: PLATFORM_DESKTOP PLATFORM_RPI PLATFORM_WEB
|
||||||
PLATFORM ?= PLATFORM_DESKTOP
|
PLATFORM ?= PLATFORM_DESKTOP
|
||||||
|
|
||||||
# define raylib graphics api depending on selected platform
|
# define raylib graphics api depending on selected platform
|
||||||
|
@ -81,7 +79,7 @@ default: raylib
|
||||||
# compile raylib library
|
# compile raylib library
|
||||||
raylib: $(OBJS)
|
raylib: $(OBJS)
|
||||||
ifeq ($(PLATFORM),PLATFORM_WEB)
|
ifeq ($(PLATFORM),PLATFORM_WEB)
|
||||||
emcc -O1 $(OBJS) -o raylib.bc
|
emcc -O1 $(OBJS) -o libraylib.bc
|
||||||
else
|
else
|
||||||
ar rcs libraylib.a $(OBJS)
|
ar rcs libraylib.a $(OBJS)
|
||||||
endif
|
endif
|
||||||
|
@ -135,9 +133,13 @@ else
|
||||||
ifeq ($(PLATFORM),PLATFORM_DESKTOP_LINUX)
|
ifeq ($(PLATFORM),PLATFORM_DESKTOP_LINUX)
|
||||||
find . -type f -executable -delete
|
find . -type f -executable -delete
|
||||||
rm -f *.o libraylib.a
|
rm -f *.o libraylib.a
|
||||||
|
else
|
||||||
|
ifeq ($(PLATFORM),PLATFORM_WEB)
|
||||||
|
del *.o libraylib.bc
|
||||||
else
|
else
|
||||||
del *.o libraylib.a
|
del *.o libraylib.a
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
@echo Cleaning done
|
@echo Cleaning done
|
||||||
|
|
||||||
|
|
42
src/models.c
42
src/models.c
|
@ -50,7 +50,7 @@
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Global Variables Definition
|
// Global Variables Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// It's lonely here...
|
extern unsigned int whiteTexture;
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module specific Functions Declaration
|
// Module specific Functions Declaration
|
||||||
|
@ -476,7 +476,7 @@ void DrawQuad(Vector3 vertices[4], Vector2 textcoords[4], Vector3 normals[4], Co
|
||||||
void DrawPlane(Vector3 centerPos, Vector2 size, Vector3 rotation, Color color)
|
void DrawPlane(Vector3 centerPos, Vector2 size, Vector3 rotation, Color color)
|
||||||
{
|
{
|
||||||
// NOTE: QUADS usage require defining a texture on OpenGL 3.3+
|
// NOTE: QUADS usage require defining a texture on OpenGL 3.3+
|
||||||
if (rlGetVersion() != OPENGL_11) rlEnableTexture(1); // Default white texture
|
if (rlGetVersion() != OPENGL_11) rlEnableTexture(whiteTexture); // Default white texture
|
||||||
|
|
||||||
// NOTE: Plane is always created on XZ ground and then rotated
|
// NOTE: Plane is always created on XZ ground and then rotated
|
||||||
rlPushMatrix();
|
rlPushMatrix();
|
||||||
|
@ -812,7 +812,7 @@ Model LoadHeightmap(Image heightmap, float maxHeight)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load a map image as a 3d model (cubes based)
|
// Load a map image as a 3d model (cubes based)
|
||||||
Model LoadCubesmap(Image cubesmap)
|
Model LoadCubicmap(Image cubesmap)
|
||||||
{
|
{
|
||||||
VertexData vData;
|
VertexData vData;
|
||||||
|
|
||||||
|
@ -1068,8 +1068,6 @@ Model LoadCubesmap(Image cubesmap)
|
||||||
// Move data from mapVertices temp arays to vertices float array
|
// Move data from mapVertices temp arays to vertices float array
|
||||||
vData.vertexCount = vCounter;
|
vData.vertexCount = vCounter;
|
||||||
|
|
||||||
//printf("Vertex count: %i\n", vCounter);
|
|
||||||
|
|
||||||
vData.vertices = (float *)malloc(vData.vertexCount * 3 * sizeof(float));
|
vData.vertices = (float *)malloc(vData.vertexCount * 3 * sizeof(float));
|
||||||
vData.normals = (float *)malloc(vData.vertexCount * 3 * sizeof(float));
|
vData.normals = (float *)malloc(vData.vertexCount * 3 * sizeof(float));
|
||||||
vData.texcoords = (float *)malloc(vData.vertexCount * 2 * sizeof(float));
|
vData.texcoords = (float *)malloc(vData.vertexCount * 2 * sizeof(float));
|
||||||
|
@ -1523,4 +1521,36 @@ static VertexData LoadOBJ(const char *fileName)
|
||||||
TraceLog(INFO, "[%s] Model loaded successfully in RAM (CPU)", fileName);
|
TraceLog(INFO, "[%s] Model loaded successfully in RAM (CPU)", fileName);
|
||||||
|
|
||||||
return vData;
|
return vData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CheckCollisionSpheres(Vector3 centerA, float radiusA, Vector3 centerB, float radiusB)
|
||||||
|
{
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CheckCollisionBoxes(Vector3 minBBox1, Vector3 maxBBox1, Vector3 minBBox2, Vector3 maxBBox2)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
// Get min and max vertex to construct bounds (AABB)
|
||||||
|
Vector3 minVertex = tempVertices[0];
|
||||||
|
Vector3 maxVertex = tempVertices[0];
|
||||||
|
|
||||||
|
for (int i = 1; i < tempVertices.Count; i++)
|
||||||
|
{
|
||||||
|
minVertex = Vector3.Min(minVertex, tempVertices[i]);
|
||||||
|
maxVertex = Vector3.Max(maxVertex, tempVertices[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
bounds = new BoundingBox(minVertex, maxVertex);
|
||||||
|
*/
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CheckCollisionBoxSphere(Vector3 minBBox, Vector3 maxBBox, Vector3 centerSphere, Vector3 radiusSphere)
|
||||||
|
{
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//BoundingBox GetCollisionArea(BoundingBox box1, BoundingBox box2)
|
12
src/raylib.h
12
src/raylib.h
|
@ -63,6 +63,7 @@
|
||||||
//#define PLATFORM_DESKTOP // Windows, Linux or OSX
|
//#define PLATFORM_DESKTOP // Windows, Linux or OSX
|
||||||
//#define PLATFORM_ANDROID // Android device
|
//#define PLATFORM_ANDROID // Android device
|
||||||
//#define PLATFORM_RPI // Raspberry Pi
|
//#define PLATFORM_RPI // Raspberry Pi
|
||||||
|
//#define PLATFORM_WEB // HTML5 (emscripten, asm.js)
|
||||||
|
|
||||||
// Security check in case no PLATFORM_* defined
|
// Security check in case no PLATFORM_* defined
|
||||||
#if !defined(PLATFORM_DESKTOP) && !defined(PLATFORM_ANDROID) && !defined(PLATFORM_RPI) && !defined(PLATFORM_WEB)
|
#if !defined(PLATFORM_DESKTOP) && !defined(PLATFORM_ANDROID) && !defined(PLATFORM_RPI) && !defined(PLATFORM_WEB)
|
||||||
|
@ -298,7 +299,7 @@ extern "C" { // Prevents name mangling of functions
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
#if defined(PLATFORM_ANDROID)
|
#if defined(PLATFORM_ANDROID)
|
||||||
void InitWindow(int width, int height, struct android_app *state); // Init Android activity
|
void InitWindow(int width, int height, struct android_app *state); // Init Android activity
|
||||||
#elif defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI)
|
#elif defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB)
|
||||||
void InitWindow(int width, int height, const char *title); // Initialize Window and OpenGL Graphics
|
void InitWindow(int width, int height, const char *title); // Initialize Window and OpenGL Graphics
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -311,6 +312,7 @@ void SetExitKey(int key); // Set a custom key
|
||||||
#endif
|
#endif
|
||||||
int GetScreenWidth(void); // Get current screen width
|
int GetScreenWidth(void); // Get current screen width
|
||||||
int GetScreenHeight(void); // Get current screen height
|
int GetScreenHeight(void); // Get current screen height
|
||||||
|
int GetKeyPressed(void); // Get latest key pressed
|
||||||
|
|
||||||
void ClearBackground(Color color); // Sets Background Color
|
void ClearBackground(Color color); // Sets Background Color
|
||||||
void BeginDrawing(void); // Setup drawing canvas to start drawing
|
void BeginDrawing(void); // Setup drawing canvas to start drawing
|
||||||
|
@ -330,8 +332,7 @@ int GetRandomValue(int min, int max); // Returns a random
|
||||||
Color Fade(Color color, float alpha); // Color fade-in or fade-out, alpha goes from 0.0f to 1.0f
|
Color Fade(Color color, float alpha); // Color fade-in or fade-out, alpha goes from 0.0f to 1.0f
|
||||||
|
|
||||||
void SetupFlags(char flags); // Enable some window configurations
|
void SetupFlags(char flags); // Enable some window configurations
|
||||||
|
void ShowLogo(void); // Activates raylib logo at startup (can be done with flags)
|
||||||
void ShowLogo(void); // Activates raylib logo at startup
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
// Input Handling Functions (Module: core)
|
// Input Handling Functions (Module: core)
|
||||||
|
@ -410,6 +411,7 @@ Texture2D LoadTextureFromImage(Image image, bool genMipmaps);
|
||||||
Texture2D CreateTexture(Image image, bool genMipmaps); // [DEPRECATED] Same as LoadTextureFromImage()
|
Texture2D CreateTexture(Image image, bool genMipmaps); // [DEPRECATED] Same as LoadTextureFromImage()
|
||||||
void UnloadImage(Image image); // Unload image from CPU memory (RAM)
|
void UnloadImage(Image image); // Unload image from CPU memory (RAM)
|
||||||
void UnloadTexture(Texture2D texture); // Unload texture from GPU memory
|
void UnloadTexture(Texture2D texture); // Unload texture from GPU memory
|
||||||
|
void ConvertToPOT(Image *image, Color fillColor); // Convert image to POT (power-of-two)
|
||||||
|
|
||||||
void DrawTexture(Texture2D texture, int posX, int posY, Color tint); // Draw a Texture2D
|
void DrawTexture(Texture2D texture, int posX, int posY, Color tint); // Draw a Texture2D
|
||||||
void DrawTextureV(Texture2D texture, Vector2 position, Color tint); // Draw a Texture2D with position defined as Vector2
|
void DrawTextureV(Texture2D texture, Vector2 position, Color tint); // Draw a Texture2D with position defined as Vector2
|
||||||
|
@ -460,7 +462,7 @@ void DrawGizmoEx(Vector3 position, Vector3 rotation, float scale);
|
||||||
Model LoadModel(const char *fileName); // Load a 3d model (.OBJ)
|
Model LoadModel(const char *fileName); // Load a 3d model (.OBJ)
|
||||||
//Model LoadModelFromRES(const char *rresName, int resId); // TODO: Load a 3d model from rRES file (raylib Resource)
|
//Model LoadModelFromRES(const char *rresName, int resId); // TODO: Load a 3d model from rRES file (raylib Resource)
|
||||||
Model LoadHeightmap(Image heightmap, float maxHeight); // Load a heightmap image as a 3d model
|
Model LoadHeightmap(Image heightmap, float maxHeight); // Load a heightmap image as a 3d model
|
||||||
Model LoadCubesmap(Image cubesmap); // Load a map image as a 3d model (cubes based)
|
Model LoadCubicmap(Image cubicmap); // Load a map image as a 3d model (cubes based)
|
||||||
void UnloadModel(Model model); // Unload 3d model from memory
|
void UnloadModel(Model model); // Unload 3d model from memory
|
||||||
void SetModelTexture(Model *model, Texture2D texture); // Link a texture to a model
|
void SetModelTexture(Model *model, Texture2D texture); // Link a texture to a model
|
||||||
|
|
||||||
|
@ -478,7 +480,7 @@ void InitAudioDevice(void); // Initialize au
|
||||||
void CloseAudioDevice(void); // Close the audio device and context (and music stream)
|
void CloseAudioDevice(void); // Close the audio device and context (and music stream)
|
||||||
|
|
||||||
Sound LoadSound(char *fileName); // Load sound to memory
|
Sound LoadSound(char *fileName); // Load sound to memory
|
||||||
Sound LoadSoundFromWave(Wave wave); // Load sound from wave data
|
Sound LoadSoundFromWave(Wave wave); // Load sound to memory from wave data
|
||||||
Sound LoadSoundFromRES(const char *rresName, int resId); // Load sound to memory from rRES file (raylib Resource)
|
Sound LoadSoundFromRES(const char *rresName, int resId); // Load sound to memory from rRES file (raylib Resource)
|
||||||
void UnloadSound(Sound sound); // Unload sound
|
void UnloadSound(Sound sound); // Unload sound
|
||||||
void PlaySound(Sound sound); // Play a sound
|
void PlaySound(Sound sound); // Play a sound
|
||||||
|
|
|
@ -329,8 +329,6 @@ void MatrixInvert(Matrix *mat)
|
||||||
// Calculate the invert determinant (inlined to avoid double-caching)
|
// Calculate the invert determinant (inlined to avoid double-caching)
|
||||||
float invDet = 1/(b00*b11 - b01*b10 + b02*b09 + b03*b08 - b04*b07 + b05*b06);
|
float invDet = 1/(b00*b11 - b01*b10 + b02*b09 + b03*b08 - b04*b07 + b05*b06);
|
||||||
|
|
||||||
printf("%f\n", invDet);
|
|
||||||
|
|
||||||
temp.m0 = (a11*b11 - a12*b10 + a13*b09)*invDet;
|
temp.m0 = (a11*b11 - a12*b10 + a13*b09)*invDet;
|
||||||
temp.m1 = (-a01*b11 + a02*b10 - a03*b09)*invDet;
|
temp.m1 = (-a01*b11 + a02*b10 - a03*b09)*invDet;
|
||||||
temp.m2 = (a31*b05 - a32*b04 + a33*b03)*invDet;
|
temp.m2 = (a31*b05 - a32*b04 + a33*b03)*invDet;
|
||||||
|
@ -492,6 +490,48 @@ Matrix MatrixRotate(float angleX, float angleY, float angleZ)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Matrix MatrixRotate(float angle, float x, float y, float z)
|
||||||
|
{
|
||||||
|
Matrix result = MatrixIdentity();
|
||||||
|
|
||||||
|
float c = cosf(angle*DEG2RAD); // cosine
|
||||||
|
float s = sinf(angle*DEG2RAD); // sine
|
||||||
|
float c1 = 1.0f - c; // 1 - c
|
||||||
|
|
||||||
|
float m0 = result.m0, m4 = result.m4, m8 = result.m8, m12 = result.m12,
|
||||||
|
m1 = result.m1, m5 = result.m5, m9 = result.m9, m13 = result.m13,
|
||||||
|
m2 = result.m2, m6 = result.m6, m10 = result.m10, m14 = result.m14;
|
||||||
|
|
||||||
|
// build rotation matrix
|
||||||
|
float r0 = x * x * c1 + c;
|
||||||
|
float r1 = x * y * c1 + z * s;
|
||||||
|
float r2 = x * z * c1 - y * s;
|
||||||
|
float r4 = x * y * c1 - z * s;
|
||||||
|
float r5 = y * y * c1 + c;
|
||||||
|
float r6 = y * z * c1 + x * s;
|
||||||
|
float r8 = x * z * c1 + y * s;
|
||||||
|
float r9 = y * z * c1 - x * s;
|
||||||
|
float r10= z * z * c1 + c;
|
||||||
|
|
||||||
|
// multiply rotation matrix
|
||||||
|
result.m0 = r0*m0 + r4*m1 + r8*m2;
|
||||||
|
result.m1 = r1*m0 + r5*m1 + r9*m2;
|
||||||
|
result.m2 = r2*m0 + r6*m1 + r10*m2;
|
||||||
|
result.m4 = r0*m4 + r4*m5 + r8*m6;
|
||||||
|
result.m5 = r1*m4 + r5*m5 + r9*m6;
|
||||||
|
result.m6 = r2*m4 + r6*m5 + r10*m6;
|
||||||
|
result.m8 = r0*m8 + r4*m9 + r8*m10;
|
||||||
|
result.m9 = r1*m8 + r5*m9 + r9*m10;
|
||||||
|
result.m10 = r2*m8 + r6*m9 + r10*m10;
|
||||||
|
result.m12 = r0*m12+ r4*m13 + r8*m14;
|
||||||
|
result.m13 = r1*m12+ r5*m13 + r9*m14;
|
||||||
|
result.m14 = r2*m12+ r6*m13 + r10*m14;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// Create rotation matrix from axis and angle
|
// Create rotation matrix from axis and angle
|
||||||
// TODO: Test this function
|
// TODO: Test this function
|
||||||
// NOTE: NO prototype defined!
|
// NOTE: NO prototype defined!
|
||||||
|
@ -668,12 +708,11 @@ Matrix MatrixScale(float x, float y, float z)
|
||||||
|
|
||||||
// Returns transformation matrix for a given translation, rotation and scale
|
// Returns transformation matrix for a given translation, rotation and scale
|
||||||
// NOTE: Transformation order is rotation -> scale -> translation
|
// NOTE: Transformation order is rotation -> scale -> translation
|
||||||
|
// NOTE: Rotation angles should come in radians
|
||||||
Matrix MatrixTransform(Vector3 translation, Vector3 rotation, Vector3 scale)
|
Matrix MatrixTransform(Vector3 translation, Vector3 rotation, Vector3 scale)
|
||||||
{
|
{
|
||||||
Matrix result = MatrixIdentity();
|
Matrix result = MatrixIdentity();
|
||||||
|
|
||||||
// TODO: Review, use DEG2RAD here?
|
|
||||||
//Matrix mRotation = MatrixRotate(rotation.x*DEG2RAD, rotation.y*DEG2RAD, rotation.z*DEG2RAD);
|
|
||||||
Matrix mRotation = MatrixRotate(rotation.x, rotation.y, rotation.z);
|
Matrix mRotation = MatrixRotate(rotation.x, rotation.y, rotation.z);
|
||||||
Matrix mScale = MatrixScale(scale.x, scale.y, scale.z);
|
Matrix mScale = MatrixScale(scale.x, scale.y, scale.z);
|
||||||
Matrix mTranslate = MatrixTranslate(translation.x, translation.y, translation.z);
|
Matrix mTranslate = MatrixTranslate(translation.x, translation.y, translation.z);
|
||||||
|
|
|
@ -55,7 +55,7 @@
|
||||||
} Vector3;
|
} Vector3;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Matrix type (OpenGL style 4x4 - right handed)
|
// Matrix type (OpenGL style 4x4 - right handed, column major)
|
||||||
typedef struct Matrix {
|
typedef struct Matrix {
|
||||||
float m0, m4, m8, m12;
|
float m0, m4, m8, m12;
|
||||||
float m1, m5, m9, m13;
|
float m1, m5, m9, m13;
|
||||||
|
@ -107,7 +107,7 @@ Matrix MatrixIdentity(void); // Returns identity matr
|
||||||
Matrix MatrixAdd(Matrix left, Matrix right); // Add two matrices
|
Matrix MatrixAdd(Matrix left, Matrix right); // Add two matrices
|
||||||
Matrix MatrixSubstract(Matrix left, Matrix right); // Substract two matrices (left - right)
|
Matrix MatrixSubstract(Matrix left, Matrix right); // Substract two matrices (left - right)
|
||||||
Matrix MatrixTranslate(float x, float y, float z); // Returns translation matrix
|
Matrix MatrixTranslate(float x, float y, float z); // Returns translation matrix
|
||||||
Matrix MatrixRotate(float angleX, float angleY, float angleZ); // Returns rotation matrix
|
Matrix MatrixRotate(float axisX, float axisY, float axisZ); // Returns rotation matrix
|
||||||
Matrix MatrixFromAxisAngle(Vector3 axis, float angle); // Returns rotation matrix for an angle around an specified axis
|
Matrix MatrixFromAxisAngle(Vector3 axis, float angle); // Returns rotation matrix for an angle around an specified axis
|
||||||
Matrix MatrixFromAxisAngle2(Vector3 axis, float angle); // Returns rotation matrix for an angle around an specified axis (test another implemntation)
|
Matrix MatrixFromAxisAngle2(Vector3 axis, float angle); // Returns rotation matrix for an angle around an specified axis (test another implemntation)
|
||||||
Matrix MatrixFromQuaternion(Quaternion q); // Returns rotation matrix for a given quaternion
|
Matrix MatrixFromQuaternion(Quaternion q); // Returns rotation matrix for a given quaternion
|
||||||
|
|
35
src/rlgl.c
35
src/rlgl.c
|
@ -169,7 +169,8 @@ static int tempBufferCount = 0;
|
||||||
static bool useTempBuffer = false;
|
static bool useTempBuffer = false;
|
||||||
|
|
||||||
// White texture useful for plain color polys (required by shader)
|
// White texture useful for plain color polys (required by shader)
|
||||||
static GLuint whiteTexture;
|
// NOTE: It's required in shapes and models modules!
|
||||||
|
extern unsigned int whiteTexture;
|
||||||
|
|
||||||
// Support for VAOs (OpenGL ES2 could not support VAO extensions)
|
// Support for VAOs (OpenGL ES2 could not support VAO extensions)
|
||||||
static bool vaoSupported = false;
|
static bool vaoSupported = false;
|
||||||
|
@ -772,7 +773,7 @@ void rlglInit(void)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(GRAPHICS_API_OPENGL_ES2)
|
#if defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
// NOTE: emscripten does not support VAOs
|
// NOTE: emscripten does not support VAOs natively, it uses emulation and it reduces overall performance...
|
||||||
#if !defined(PLATFORM_WEB)
|
#if !defined(PLATFORM_WEB)
|
||||||
glGenVertexArrays = (PFNGLGENVERTEXARRAYSOESPROC)eglGetProcAddress("glGenVertexArraysOES");
|
glGenVertexArrays = (PFNGLGENVERTEXARRAYSOESPROC)eglGetProcAddress("glGenVertexArraysOES");
|
||||||
glBindVertexArray = (PFNGLBINDVERTEXARRAYOESPROC)eglGetProcAddress("glBindVertexArrayOES");
|
glBindVertexArray = (PFNGLBINDVERTEXARRAYOESPROC)eglGetProcAddress("glBindVertexArrayOES");
|
||||||
|
@ -1128,6 +1129,8 @@ void rlglDrawModel(Model model, Vector3 position, Vector3 rotation, Vector3 scal
|
||||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
glUseProgram(shaderProgram); // Use our shader
|
glUseProgram(shaderProgram); // Use our shader
|
||||||
|
|
||||||
|
VectorScale(&rotation, DEG2RAD);
|
||||||
|
|
||||||
// Get transform matrix (rotation -> scale -> translation)
|
// Get transform matrix (rotation -> scale -> translation)
|
||||||
Matrix transform = MatrixTransform(position, rotation, scale);
|
Matrix transform = MatrixTransform(position, rotation, scale);
|
||||||
Matrix modelviewworld = MatrixMultiply(transform, modelview);
|
Matrix modelviewworld = MatrixMultiply(transform, modelview);
|
||||||
|
@ -1340,7 +1343,7 @@ unsigned int rlglLoadTexture(unsigned char *data, int width, int height, bool ge
|
||||||
// Unbind current texture
|
// Unbind current texture
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
TraceLog(INFO, "[TEX ID %i] Texture created successfully (%i x %i)", id, width, height);
|
TraceLog(INFO, "[TEX ID %i] Texture created successfully (%ix%i)", id, width, height);
|
||||||
|
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
@ -1690,33 +1693,35 @@ static GLuint LoadShaders(char *vertexFileName, char *fragmentFileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read shader text file
|
// Read shader text file
|
||||||
static char *TextFileRead(char *fn)
|
static char *TextFileRead(char *fileName)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *textFile;
|
||||||
char *text = NULL;
|
char *text = NULL;
|
||||||
|
|
||||||
int count=0;
|
int count=0;
|
||||||
|
|
||||||
if (fn != NULL)
|
if (fileName != NULL)
|
||||||
{
|
{
|
||||||
fp = fopen(fn,"rt");
|
textFile = fopen(fileName,"rt");
|
||||||
|
|
||||||
if (fp != NULL)
|
if (textFile != NULL)
|
||||||
{
|
{
|
||||||
fseek(fp, 0, SEEK_END);
|
fseek(textFile, 0, SEEK_END);
|
||||||
count = ftell(fp);
|
count = ftell(textFile);
|
||||||
rewind(fp);
|
rewind(textFile);
|
||||||
|
|
||||||
if (count > 0)
|
if (count > 0)
|
||||||
{
|
{
|
||||||
text = (char *)malloc(sizeof(char) * (count+1));
|
text = (char *)malloc(sizeof(char) * (count+1));
|
||||||
count = fread(text, sizeof(char), count, fp);
|
count = fread(text, sizeof(char), count, textFile);
|
||||||
text[count] = '\0';
|
text[count] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(fp);
|
fclose(textFile);
|
||||||
}
|
}
|
||||||
|
else TraceLog(WARNING, "[%s] Text file could not be opened", fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1992,7 +1997,7 @@ static int GenerateMipmaps(unsigned char *data, int baseWidth, int baseHeight)
|
||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
|
|
||||||
TraceLog(DEBUG, "Mipmap base (%i, %i)", width, height);
|
TraceLog(DEBUG, "Mipmap base (%ix%i)", width, height);
|
||||||
|
|
||||||
for (int mip = 1; mip < mipmapCount; mip++)
|
for (int mip = 1; mip < mipmapCount; mip++)
|
||||||
{
|
{
|
||||||
|
@ -2063,7 +2068,7 @@ static pixel *GenNextMipmap(pixel *srcData, int srcWidth, int srcHeight)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TraceLog(DEBUG, "Mipmap generated successfully (%i, %i)", width, height);
|
TraceLog(DEBUG, "Mipmap generated successfully (%ix%i)", width, height);
|
||||||
|
|
||||||
return mipmap;
|
return mipmap;
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,8 +72,9 @@
|
||||||
#define MAX_TRIANGLES_BATCH 4096
|
#define MAX_TRIANGLES_BATCH 4096
|
||||||
#define MAX_QUADS_BATCH 4096
|
#define MAX_QUADS_BATCH 4096
|
||||||
#elif defined(GRAPHICS_API_OPENGL_ES2)
|
#elif defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
// NOTE: Reduce memory sizes for embedded systems (RPI)
|
// NOTE: Reduce memory sizes for embedded systems (RPI and HTML5)
|
||||||
#define MAX_LINES_BATCH 2048 // Critical for wire shapes (sphere)
|
// NOTE: On HTML5 (emscripten) this is allocated on heap, by default it's only 16MB!...just take care...
|
||||||
|
#define MAX_LINES_BATCH 1024 // Critical for wire shapes (sphere)
|
||||||
#define MAX_TRIANGLES_BATCH 2048 // Critical for some shapes (sphere)
|
#define MAX_TRIANGLES_BATCH 2048 // Critical for some shapes (sphere)
|
||||||
#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
|
||||||
|
|
|
@ -44,7 +44,7 @@
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Global Variables Definition
|
// Global Variables Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// It's lonely here...
|
extern unsigned int whiteTexture;
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module specific Functions Declaration
|
// Module specific Functions Declaration
|
||||||
|
@ -197,7 +197,7 @@ void DrawRectangleV(Vector2 position, Vector2 size, Color color)
|
||||||
else if ((rlGetVersion() == OPENGL_33) || (rlGetVersion() == OPENGL_ES_20))
|
else if ((rlGetVersion() == OPENGL_33) || (rlGetVersion() == OPENGL_ES_20))
|
||||||
{
|
{
|
||||||
// NOTE: This shape uses QUADS to avoid drawing order issues (view rlglDraw)
|
// NOTE: This shape uses QUADS to avoid drawing order issues (view rlglDraw)
|
||||||
rlEnableTexture(1); // Default white texture
|
rlEnableTexture(whiteTexture); // Default white texture
|
||||||
|
|
||||||
rlBegin(RL_QUADS);
|
rlBegin(RL_QUADS);
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
|
198
src/text.c
198
src/text.c
|
@ -63,7 +63,6 @@ static SpriteFont defaultFont; // Default font provided by raylib
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
static bool PixelIsMagenta(Color p); // Check if a pixel is magenta
|
static bool PixelIsMagenta(Color p); // Check if a pixel is magenta
|
||||||
static int ParseImageData(Color *imgDataPixel, int imgWidth, int imgHeight, Character **charSet); // Parse image pixel data to obtain character set measures
|
static int ParseImageData(Color *imgDataPixel, int imgWidth, int imgHeight, Character **charSet); // Parse image pixel data to obtain character set measures
|
||||||
static int GetNextPOT(int num); // Calculate next power-of-two value for a given value
|
|
||||||
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)
|
||||||
|
|
||||||
extern void LoadDefaultFont(void);
|
extern void LoadDefaultFont(void);
|
||||||
|
@ -195,9 +194,10 @@ SpriteFont LoadSpriteFont(const char *fileName)
|
||||||
Image image = LoadImage(fileName);
|
Image image = LoadImage(fileName);
|
||||||
|
|
||||||
// At this point we have a pixel array with all the data...
|
// At this point we have a pixel array with all the data...
|
||||||
|
|
||||||
TraceLog(INFO, "[%s] SpriteFont image loaded: %i x %i", fileName, image.width, image.height);
|
#if defined(PLATFORM_RPI) || defined(PLATFORM_WEB)
|
||||||
|
ConvertToPOT(&image, MAGENTA);
|
||||||
|
#endif
|
||||||
// Process bitmap Font pixel data to get measures (Character array)
|
// Process bitmap Font pixel data to get measures (Character array)
|
||||||
// spriteFont.charSet data is filled inside the function and memory is allocated!
|
// spriteFont.charSet data is filled inside the function and memory is allocated!
|
||||||
int numChars = ParseImageData(image.pixels, image.width, image.height, &spriteFont.charSet);
|
int numChars = ParseImageData(image.pixels, image.width, image.height, &spriteFont.charSet);
|
||||||
|
@ -207,40 +207,8 @@ SpriteFont LoadSpriteFont(const char *fileName)
|
||||||
|
|
||||||
spriteFont.numChars = numChars;
|
spriteFont.numChars = numChars;
|
||||||
|
|
||||||
// Convert image font to POT image before conversion to texture
|
|
||||||
// NOTE: Not required, we skip this step
|
|
||||||
/*
|
|
||||||
// Just add the required amount of pixels at the right and bottom sides of image...
|
|
||||||
int potWidth = GetNextPOT(image.width);
|
|
||||||
int potHeight = GetNextPOT(image.height);
|
|
||||||
|
|
||||||
// Check if POT texture generation is required (if texture is not already POT)
|
|
||||||
if ((potWidth != image.width) || (potHeight != image.height))
|
|
||||||
{
|
|
||||||
Color *imgDataPixelPOT = NULL;
|
|
||||||
|
|
||||||
// Generate POT array from NPOT data
|
|
||||||
imgDataPixelPOT = (Color *)malloc(potWidth * potHeight * sizeof(Color));
|
|
||||||
|
|
||||||
for (int j = 0; j < potHeight; j++)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < potWidth; i++)
|
|
||||||
{
|
|
||||||
if ((j < image.height) && (i < image.width)) imgDataPixelPOT[j*potWidth + i] = image.pixels[j*image.width + i];
|
|
||||||
else imgDataPixelPOT[j*potWidth + i] = MAGENTA;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TraceLog(WARNING, "SpriteFont texture converted to POT: %ix%i", potWidth, potHeight);
|
|
||||||
|
|
||||||
free(image.pixels);
|
|
||||||
|
|
||||||
image.pixels = imgDataPixelPOT;
|
|
||||||
image.width = potWidth;
|
|
||||||
image.height = potHeight;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
spriteFont.texture = LoadTextureFromImage(image, false); // Convert loaded image to OpenGL texture
|
spriteFont.texture = LoadTextureFromImage(image, false); // Convert loaded image to OpenGL texture
|
||||||
|
|
||||||
UnloadImage(image);
|
UnloadImage(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -475,23 +443,6 @@ static int ParseImageData(Color *imgDataPixel, int imgWidth, int imgHeight, Char
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate next power-of-two value for a given num
|
|
||||||
static int GetNextPOT(int num)
|
|
||||||
{
|
|
||||||
if (num != 0)
|
|
||||||
{
|
|
||||||
num--;
|
|
||||||
num |= (num >> 1); // Or first 2 bits
|
|
||||||
num |= (num >> 2); // Or next 2 bits
|
|
||||||
num |= (num >> 4); // Or next 4 bits
|
|
||||||
num |= (num >> 8); // Or next 8 bits
|
|
||||||
num |= (num >> 16); // Or next 16 bits
|
|
||||||
num++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return num;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load a rBMF font file (raylib BitMap Font)
|
// Load a rBMF font file (raylib BitMap Font)
|
||||||
static SpriteFont LoadRBMF(const char *fileName)
|
static SpriteFont LoadRBMF(const char *fileName)
|
||||||
{
|
{
|
||||||
|
@ -517,91 +468,96 @@ static SpriteFont LoadRBMF(const char *fileName)
|
||||||
Image image;
|
Image image;
|
||||||
|
|
||||||
rbmfInfoHeader rbmfHeader;
|
rbmfInfoHeader rbmfHeader;
|
||||||
unsigned int *rbmfFileData;
|
unsigned int *rbmfFileData = NULL;
|
||||||
unsigned char *rbmfCharWidthData;
|
unsigned char *rbmfCharWidthData = NULL;
|
||||||
|
|
||||||
int charsDivisor = 1; // Every char is separated from the consecutive by a 1 pixel divisor, horizontally and vertically
|
int charsDivisor = 1; // Every char is separated from the consecutive by a 1 pixel divisor, horizontally and vertically
|
||||||
|
|
||||||
FILE *rbmfFile = fopen(fileName, "rb"); // Define a pointer to bitmap file and open it in read-binary mode
|
FILE *rbmfFile = fopen(fileName, "rb"); // Define a pointer to bitmap file and open it in read-binary mode
|
||||||
|
|
||||||
// TODO: Check if file could be loaded! (rbmfFile == NULL)?
|
if (rbmfFile == NULL)
|
||||||
|
|
||||||
fread(&rbmfHeader, sizeof(rbmfInfoHeader), 1, rbmfFile);
|
|
||||||
|
|
||||||
TraceLog(INFO, "[%s] Loading rBMF file, size: %ix%i, numChars: %i, charHeight: %i", fileName, rbmfHeader.imgWidth, rbmfHeader.imgHeight, rbmfHeader.numChars, rbmfHeader.charHeight);
|
|
||||||
|
|
||||||
spriteFont.numChars = (int)rbmfHeader.numChars;
|
|
||||||
|
|
||||||
image.width = (int)rbmfHeader.imgWidth;
|
|
||||||
image.height = (int)rbmfHeader.imgHeight;
|
|
||||||
|
|
||||||
int numPixelBits = rbmfHeader.imgWidth * rbmfHeader.imgHeight / 32;
|
|
||||||
|
|
||||||
rbmfFileData = (unsigned int *)malloc(numPixelBits * sizeof(unsigned int));
|
|
||||||
|
|
||||||
for(int i = 0; i < numPixelBits; i++) fread(&rbmfFileData[i], sizeof(unsigned int), 1, rbmfFile);
|
|
||||||
|
|
||||||
rbmfCharWidthData = (unsigned char *)malloc(spriteFont.numChars * sizeof(unsigned char));
|
|
||||||
|
|
||||||
for(int i = 0; i < spriteFont.numChars; i++) fread(&rbmfCharWidthData[i], sizeof(unsigned char), 1, rbmfFile);
|
|
||||||
|
|
||||||
// Re-construct image from rbmfFileData
|
|
||||||
//-----------------------------------------
|
|
||||||
image.pixels = (Color *)malloc(image.width * image.height * sizeof(Color));
|
|
||||||
|
|
||||||
for (int i = 0; i < image.width * image.height; i++) image.pixels[i] = BLANK; // Initialize array
|
|
||||||
|
|
||||||
int counter = 0; // Font data elements counter
|
|
||||||
|
|
||||||
// Fill image data (convert from bit to pixel!)
|
|
||||||
for (int i = 0; i < image.width * image.height; i += 32)
|
|
||||||
{
|
{
|
||||||
for (int j = 31; j >= 0; j--)
|
TraceLog(WARNING, "[%s] rBMF font file could not be opened", fileName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fread(&rbmfHeader, sizeof(rbmfInfoHeader), 1, rbmfFile);
|
||||||
|
|
||||||
|
TraceLog(INFO, "[%s] Loading rBMF file, size: %ix%i, numChars: %i, charHeight: %i", fileName, rbmfHeader.imgWidth, rbmfHeader.imgHeight, rbmfHeader.numChars, rbmfHeader.charHeight);
|
||||||
|
|
||||||
|
spriteFont.numChars = (int)rbmfHeader.numChars;
|
||||||
|
|
||||||
|
image.width = (int)rbmfHeader.imgWidth;
|
||||||
|
image.height = (int)rbmfHeader.imgHeight;
|
||||||
|
|
||||||
|
int numPixelBits = rbmfHeader.imgWidth * rbmfHeader.imgHeight / 32;
|
||||||
|
|
||||||
|
rbmfFileData = (unsigned int *)malloc(numPixelBits * sizeof(unsigned int));
|
||||||
|
|
||||||
|
for(int i = 0; i < numPixelBits; i++) fread(&rbmfFileData[i], sizeof(unsigned int), 1, rbmfFile);
|
||||||
|
|
||||||
|
rbmfCharWidthData = (unsigned char *)malloc(spriteFont.numChars * sizeof(unsigned char));
|
||||||
|
|
||||||
|
for(int i = 0; i < spriteFont.numChars; i++) fread(&rbmfCharWidthData[i], sizeof(unsigned char), 1, rbmfFile);
|
||||||
|
|
||||||
|
// Re-construct image from rbmfFileData
|
||||||
|
//-----------------------------------------
|
||||||
|
image.pixels = (Color *)malloc(image.width * image.height * sizeof(Color));
|
||||||
|
|
||||||
|
for (int i = 0; i < image.width * image.height; i++) image.pixels[i] = BLANK; // Initialize array
|
||||||
|
|
||||||
|
int counter = 0; // Font data elements counter
|
||||||
|
|
||||||
|
// Fill image data (convert from bit to pixel!)
|
||||||
|
for (int i = 0; i < image.width * image.height; i += 32)
|
||||||
{
|
{
|
||||||
if (BIT_CHECK(rbmfFileData[counter], j)) image.pixels[i+j] = WHITE;
|
for (int j = 31; j >= 0; j--)
|
||||||
|
{
|
||||||
|
if (BIT_CHECK(rbmfFileData[counter], j)) image.pixels[i+j] = WHITE;
|
||||||
|
}
|
||||||
|
|
||||||
|
counter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
counter++;
|
TraceLog(INFO, "[%s] Image reconstructed correctly, now converting it to texture", fileName);
|
||||||
}
|
|
||||||
|
|
||||||
TraceLog(INFO, "[%s] Image reconstructed correctly, now converting it to texture", fileName);
|
spriteFont.texture = LoadTextureFromImage(image, false);
|
||||||
|
UnloadImage(image); // Unload image data
|
||||||
|
|
||||||
spriteFont.texture = LoadTextureFromImage(image, false);
|
//TraceLog(INFO, "[%s] Starting charSet reconstruction", fileName);
|
||||||
UnloadImage(image); // Unload image data
|
|
||||||
|
|
||||||
TraceLog(INFO, "[%s] Starting charSet reconstruction", fileName);
|
// Reconstruct charSet using rbmfCharWidthData, rbmfHeader.charHeight, charsDivisor, rbmfHeader.numChars
|
||||||
|
spriteFont.charSet = (Character *)malloc(spriteFont.numChars * sizeof(Character)); // Allocate space for our character data
|
||||||
|
|
||||||
// Reconstruct charSet using rbmfCharWidthData, rbmfHeader.charHeight, charsDivisor, rbmfHeader.numChars
|
int currentLine = 0;
|
||||||
spriteFont.charSet = (Character *)malloc(spriteFont.numChars * sizeof(Character)); // Allocate space for our character data
|
int currentPosX = charsDivisor;
|
||||||
|
int testPosX = charsDivisor;
|
||||||
|
|
||||||
int currentLine = 0;
|
for (int i = 0; i < spriteFont.numChars; i++)
|
||||||
int currentPosX = charsDivisor;
|
|
||||||
int testPosX = charsDivisor;
|
|
||||||
|
|
||||||
for (int i = 0; i < spriteFont.numChars; i++)
|
|
||||||
{
|
|
||||||
spriteFont.charSet[i].value = (int)rbmfHeader.firstChar + i;
|
|
||||||
spriteFont.charSet[i].x = currentPosX;
|
|
||||||
spriteFont.charSet[i].y = charsDivisor + currentLine * ((int)rbmfHeader.charHeight + charsDivisor);
|
|
||||||
spriteFont.charSet[i].w = (int)rbmfCharWidthData[i];
|
|
||||||
spriteFont.charSet[i].h = (int)rbmfHeader.charHeight;
|
|
||||||
|
|
||||||
testPosX += (spriteFont.charSet[i].w + charsDivisor);
|
|
||||||
|
|
||||||
if (testPosX > spriteFont.texture.width)
|
|
||||||
{
|
{
|
||||||
currentLine++;
|
spriteFont.charSet[i].value = (int)rbmfHeader.firstChar + i;
|
||||||
currentPosX = 2 * charsDivisor + (int)rbmfCharWidthData[i];
|
spriteFont.charSet[i].x = currentPosX;
|
||||||
testPosX = currentPosX;
|
spriteFont.charSet[i].y = charsDivisor + currentLine * ((int)rbmfHeader.charHeight + charsDivisor);
|
||||||
|
spriteFont.charSet[i].w = (int)rbmfCharWidthData[i];
|
||||||
|
spriteFont.charSet[i].h = (int)rbmfHeader.charHeight;
|
||||||
|
|
||||||
spriteFont.charSet[i].x = charsDivisor;
|
testPosX += (spriteFont.charSet[i].w + charsDivisor);
|
||||||
spriteFont.charSet[i].y = charsDivisor + currentLine * (rbmfHeader.charHeight + charsDivisor);
|
|
||||||
|
if (testPosX > spriteFont.texture.width)
|
||||||
|
{
|
||||||
|
currentLine++;
|
||||||
|
currentPosX = 2 * charsDivisor + (int)rbmfCharWidthData[i];
|
||||||
|
testPosX = currentPosX;
|
||||||
|
|
||||||
|
spriteFont.charSet[i].x = charsDivisor;
|
||||||
|
spriteFont.charSet[i].y = charsDivisor + currentLine * (rbmfHeader.charHeight + charsDivisor);
|
||||||
|
}
|
||||||
|
else currentPosX = testPosX;
|
||||||
}
|
}
|
||||||
else currentPosX = testPosX;
|
|
||||||
|
TraceLog(INFO, "[%s] rBMF file loaded correctly as SpriteFont", fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
TraceLog(INFO, "[%s] rBMF file loaded correctly as SpriteFont", fileName);
|
|
||||||
|
|
||||||
fclose(rbmfFile);
|
fclose(rbmfFile);
|
||||||
|
|
||||||
free(rbmfFileData); // Now we can free loaded data from RAM memory
|
free(rbmfFileData); // Now we can free loaded data from RAM memory
|
||||||
|
|
|
@ -126,7 +126,7 @@ Image LoadImage(const char *fileName)
|
||||||
image.width = imgWidth;
|
image.width = imgWidth;
|
||||||
image.height = imgHeight;
|
image.height = imgHeight;
|
||||||
|
|
||||||
TraceLog(INFO, "[%s] Image loaded successfully", fileName);
|
TraceLog(INFO, "[%s] Image loaded successfully (%ix%i)", fileName, image.width, image.height);
|
||||||
}
|
}
|
||||||
else TraceLog(WARNING, "[%s] Image could not be loaded, file not recognized", fileName);
|
else TraceLog(WARNING, "[%s] Image could not be loaded, file not recognized", fileName);
|
||||||
}
|
}
|
||||||
|
@ -187,7 +187,10 @@ Image LoadImageFromRES(const char *rresName, int resId)
|
||||||
|
|
||||||
FILE *rresFile = fopen(rresName, "rb");
|
FILE *rresFile = fopen(rresName, "rb");
|
||||||
|
|
||||||
if (!rresFile) TraceLog(WARNING, "[%s] Could not open raylib resource file", rresName);
|
if (rresFile == NULL)
|
||||||
|
{
|
||||||
|
TraceLog(WARNING, "[%s] rRES raylib resource file could not be opened", rresName);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Read rres file (basic file check - id)
|
// Read rres file (basic file check - id)
|
||||||
|
@ -337,9 +340,12 @@ Texture2D LoadTexture(const char *fileName)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Image image = LoadImage(fileName);
|
Image image = LoadImage(fileName);
|
||||||
|
|
||||||
if (image.pixels != NULL)
|
if (image.pixels != NULL)
|
||||||
{
|
{
|
||||||
|
#if defined(PLATFORM_RPI) || defined(PLATFORM_WEB)
|
||||||
|
ConvertToPOT(&image, BLANK);
|
||||||
|
#endif
|
||||||
texture = LoadTextureFromImage(image, false);
|
texture = LoadTextureFromImage(image, false);
|
||||||
UnloadImage(image);
|
UnloadImage(image);
|
||||||
}
|
}
|
||||||
|
@ -425,6 +431,41 @@ void UnloadTexture(Texture2D texture)
|
||||||
rlDeleteTextures(texture.id);
|
rlDeleteTextures(texture.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Convert image to POT (power-of-two)
|
||||||
|
// NOTE: Requirement on OpenGL ES 2.0 (RPI, HTML5)
|
||||||
|
void ConvertToPOT(Image *image, Color fillColor)
|
||||||
|
{
|
||||||
|
// Just add the required amount of pixels at the right and bottom sides of image...
|
||||||
|
int potWidth = GetNextPOT(image->width);
|
||||||
|
int potHeight = GetNextPOT(image->height);
|
||||||
|
|
||||||
|
// Check if POT texture generation is required (if texture is not already POT)
|
||||||
|
if ((potWidth != image->width) || (potHeight != image->height))
|
||||||
|
{
|
||||||
|
Color *imgDataPixelPOT = NULL;
|
||||||
|
|
||||||
|
// Generate POT array from NPOT data
|
||||||
|
imgDataPixelPOT = (Color *)malloc(potWidth * potHeight * sizeof(Color));
|
||||||
|
|
||||||
|
for (int j = 0; j < potHeight; j++)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < potWidth; i++)
|
||||||
|
{
|
||||||
|
if ((j < image->height) && (i < image->width)) imgDataPixelPOT[j*potWidth + i] = image->pixels[j*image->width + i];
|
||||||
|
else imgDataPixelPOT[j*potWidth + i] = fillColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TraceLog(WARNING, "Image converted to POT: (%ix%i) -> (%ix%i)", image->width, image->height, potWidth, potHeight);
|
||||||
|
|
||||||
|
free(image->pixels);
|
||||||
|
|
||||||
|
image->pixels = imgDataPixelPOT;
|
||||||
|
image->width = potWidth;
|
||||||
|
image->height = potHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Draw a Texture2D
|
// Draw a Texture2D
|
||||||
void DrawTexture(Texture2D texture, int posX, int posY, Color tint)
|
void DrawTexture(Texture2D texture, int posX, int posY, Color tint)
|
||||||
{
|
{
|
||||||
|
@ -559,7 +600,7 @@ static ImageEx LoadDDS(const char *fileName)
|
||||||
|
|
||||||
if (ddsFile == NULL)
|
if (ddsFile == NULL)
|
||||||
{
|
{
|
||||||
TraceLog(WARNING, "DDS File could not be opened");
|
TraceLog(WARNING, "[%s] DDS image file could not be opened", fileName);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -570,7 +611,7 @@ static ImageEx LoadDDS(const char *fileName)
|
||||||
|
|
||||||
if (strncmp(filecode, "DDS ", 4) != 0)
|
if (strncmp(filecode, "DDS ", 4) != 0)
|
||||||
{
|
{
|
||||||
TraceLog(WARNING, "DDS File does not seem to be valid");
|
TraceLog(WARNING, "[%s] DDS file does not seem to be a valid image", fileName);
|
||||||
fclose(ddsFile);
|
fclose(ddsFile);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -705,7 +746,7 @@ static ImageEx LoadPKM(const char *fileName)
|
||||||
|
|
||||||
if (pkmFile == NULL)
|
if (pkmFile == NULL)
|
||||||
{
|
{
|
||||||
TraceLog(WARNING, "[%s] PKM File could not be opened", fileName);
|
TraceLog(WARNING, "[%s] PKM image file could not be opened", fileName);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -716,7 +757,7 @@ static ImageEx LoadPKM(const char *fileName)
|
||||||
|
|
||||||
if (strncmp(filecode, "PKM ", 4) != 0)
|
if (strncmp(filecode, "PKM ", 4) != 0)
|
||||||
{
|
{
|
||||||
TraceLog(WARNING, "[%s] PKM File does not seem to be valid", fileName);
|
TraceLog(WARNING, "[%s] PKM file does not seem to be a valid image", fileName);
|
||||||
fclose(pkmFile);
|
fclose(pkmFile);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
44
src/utils.c
44
src/utils.c
|
@ -133,18 +133,25 @@ void WriteBitmap(const char *fileName, unsigned char *imgData, int width, int he
|
||||||
|
|
||||||
FILE *bmpFile = fopen(fileName, "wb"); // Define a pointer to bitmap file and open it in write-binary mode
|
FILE *bmpFile = fopen(fileName, "wb"); // Define a pointer to bitmap file and open it in write-binary mode
|
||||||
|
|
||||||
// NOTE: fwrite parameters are: data pointer, size in bytes of each element to be written, number of elements, file-to-write pointer
|
if (bmpFile == NULL)
|
||||||
fwrite(bmpFileHeader, sizeof(unsigned char), 14, bmpFile); // Write BMP file header data
|
|
||||||
fwrite(bmpInfoHeader, sizeof(unsigned char), 40, bmpFile); // Write BMP info header data
|
|
||||||
|
|
||||||
// Write pixel data to file
|
|
||||||
for (int y = 0; y < height ; y++)
|
|
||||||
{
|
{
|
||||||
for (int x = 0; x < width; x++)
|
TraceLog(WARNING, "[%s] BMP file could not be created", fileName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// NOTE: fwrite parameters are: data pointer, size in bytes of each element to be written, number of elements, file-to-write pointer
|
||||||
|
fwrite(bmpFileHeader, sizeof(unsigned char), 14, bmpFile); // Write BMP file header data
|
||||||
|
fwrite(bmpInfoHeader, sizeof(unsigned char), 40, bmpFile); // Write BMP info header data
|
||||||
|
|
||||||
|
// Write pixel data to file
|
||||||
|
for (int y = 0; y < height ; y++)
|
||||||
{
|
{
|
||||||
fputc(imgData[(x*4)+2 + (y*width*4)], bmpFile);
|
for (int x = 0; x < width; x++)
|
||||||
fputc(imgData[(x*4)+1 + (y*width*4)], bmpFile);
|
{
|
||||||
fputc(imgData[(x*4) + (y*width*4)], bmpFile);
|
fputc(imgData[(x*4)+2 + (y*width*4)], bmpFile);
|
||||||
|
fputc(imgData[(x*4)+1 + (y*width*4)], bmpFile);
|
||||||
|
fputc(imgData[(x*4) + (y*width*4)], bmpFile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,6 +271,23 @@ const char *GetExtension(const char *fileName)
|
||||||
return (dot + 1);
|
return (dot + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Calculate next power-of-two value for a given num
|
||||||
|
int GetNextPOT(int num)
|
||||||
|
{
|
||||||
|
if (num != 0)
|
||||||
|
{
|
||||||
|
num--;
|
||||||
|
num |= (num >> 1); // Or first 2 bits
|
||||||
|
num |= (num >> 2); // Or next 2 bits
|
||||||
|
num |= (num >> 4); // Or next 4 bits
|
||||||
|
num |= (num >> 8); // Or next 8 bits
|
||||||
|
num |= (num >> 16); // Or next 16 bits
|
||||||
|
num++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module specific Functions Definition
|
// Module specific Functions Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
|
@ -77,6 +77,7 @@ void WritePNG(const char *fileName, unsigned char *imgData, int width, int heigh
|
||||||
|
|
||||||
void TraceLog(int msgType, const char *text, ...); // Outputs a trace log message
|
void TraceLog(int msgType, const char *text, ...); // Outputs a trace log message
|
||||||
const char *GetExtension(const char *fileName); // Returns extension of a filename
|
const char *GetExtension(const char *fileName); // Returns extension of a filename
|
||||||
|
int GetNextPOT(int num); // Calculate next power-of-two value for a given num
|
||||||
|
|
||||||
#if defined(PLATFORM_ANDROID)
|
#if defined(PLATFORM_ANDROID)
|
||||||
void InitAssetManager(AAssetManager *manager); // Initialize asset manager from android app
|
void InitAssetManager(AAssetManager *manager); // Initialize asset manager from android app
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue