Removed useless spaces

This commit is contained in:
raysan5 2014-09-03 16:51:28 +02:00
parent 222995c32e
commit d2b98fbb5c
13 changed files with 1288 additions and 1288 deletions

View File

@ -3,21 +3,21 @@
* raylib.audio
*
* Basic functions to manage Audio: InitAudioDevice, LoadAudioFiles, PlayAudioFiles
*
* Uses external lib:
*
* Uses external lib:
* OpenAL - Audio device management lib
* stb_vorbis - Ogg audio files loading
*
*
* Copyright (c) 2013 Ramon Santamaria (Ray San - raysan@raysanweb.com)
*
* 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.
*
* Permission is granted to anyone to use this software for any purpose, including commercial
* Permission is granted to anyone to use this software for any purpose, including commercial
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* in the product documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
@ -54,16 +54,16 @@
// NOTE: Anything longer than ~10 seconds should be streamed...
typedef struct Music {
stb_vorbis *stream;
ALuint buffers[MUSIC_STREAM_BUFFERS];
ALuint source;
ALenum format;
ALuint buffers[MUSIC_STREAM_BUFFERS];
ALuint source;
ALenum format;
int channels;
int sampleRate;
int totalSamplesLeft;
bool loop;
int totalSamplesLeft;
bool loop;
} Music;
// Wave file data
@ -72,7 +72,7 @@ typedef struct Wave {
unsigned int dataSize; // Data size in bytes
unsigned int sampleRate;
short bitsPerSample;
short channels;
short channels;
} Wave;
//----------------------------------------------------------------------------------
@ -102,22 +102,22 @@ void InitAudioDevice()
{
// Open and initialize a device with default settings
ALCdevice *device = alcOpenDevice(NULL);
if(!device) TraceLog(ERROR, "Could not open audio device");
ALCcontext *context = alcCreateContext(device, NULL);
if(context == NULL || alcMakeContextCurrent(context) == ALC_FALSE)
{
if(context != NULL) alcDestroyContext(context);
alcCloseDevice(device);
TraceLog(ERROR, "Could not setup audio context");
}
TraceLog(INFO, "Audio device and context initialized successfully: %s\n", alcGetString(device, ALC_DEVICE_SPECIFIER));
// Listener definition (just for 2D)
alListener3f(AL_POSITION, 0, 0, 0);
alListener3f(AL_VELOCITY, 0, 0, 0);
@ -131,7 +131,7 @@ void CloseAudioDevice()
ALCdevice *device;
ALCcontext *context = alcGetCurrentContext();
if (context == NULL) TraceLog(WARNING, "Could not get current audio context for closing");
device = alcGetContextsDevice(context);
@ -150,41 +150,41 @@ Sound LoadSound(char *fileName)
{
Sound sound;
Wave wave;
// NOTE: The entire file is loaded to memory to play it all at once (no-streaming)
// Audio file loading
// NOTE: Buffer space is allocated inside function, Wave must be freed
if (strcmp(GetExtension(fileName),"wav") == 0) wave = LoadWAV(fileName);
else if (strcmp(GetExtension(fileName),"ogg") == 0) wave = LoadOGG(fileName);
else TraceLog(WARNING, "[%s] Sound extension not recognized, it can't be loaded", fileName);
if (wave.data != NULL)
{
ALenum format = 0;
// The OpenAL format is worked out by looking at the number of channels and the bits per sample
if (wave.channels == 1)
if (wave.channels == 1)
{
if (wave.bitsPerSample == 8 ) format = AL_FORMAT_MONO8;
else if (wave.bitsPerSample == 16) format = AL_FORMAT_MONO16;
}
else if (wave.channels == 2)
}
else if (wave.channels == 2)
{
if (wave.bitsPerSample == 8 ) format = AL_FORMAT_STEREO8;
else if (wave.bitsPerSample == 16) format = AL_FORMAT_STEREO16;
}
// Create an audio source
ALuint source;
alGenSources(1, &source); // Generate pointer to audio source
alSourcef(source, AL_PITCH, 1);
alSourcef(source, AL_PITCH, 1);
alSourcef(source, AL_GAIN, 1);
alSource3f(source, AL_POSITION, 0, 0, 0);
alSource3f(source, AL_VELOCITY, 0, 0, 0);
alSourcei(source, AL_LOOPING, AL_FALSE);
// Convert loaded data to OpenAL buffer
//----------------------------------------
ALuint buffer;
@ -195,17 +195,17 @@ Sound LoadSound(char *fileName)
// Attach sound buffer to source
alSourcei(source, AL_BUFFER, buffer);
// Unallocate WAV data
UnloadWave(wave);
TraceLog(INFO, "[%s] Sound file loaded successfully", fileName);
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.buffer = buffer;
}
return sound;
}
@ -220,9 +220,9 @@ Sound LoadSoundFromRES(const char *rresName, int resId)
unsigned char version; // rRES file version and subversion
char useless; // rRES header reserved data
short numRes;
ResInfoHeader infoHeader;
FILE *rresFile = fopen(rresName, "rb");
if (!rresFile) TraceLog(WARNING, "[%s] Could not open raylib resource file", rresName);
@ -235,7 +235,7 @@ Sound LoadSoundFromRES(const char *rresName, int resId)
fread(&id[3], sizeof(char), 1, rresFile);
fread(&version, sizeof(char), 1, rresFile);
fread(&useless, sizeof(char), 1, rresFile);
if ((id[0] != 'r') && (id[1] != 'R') && (id[2] != 'E') &&(id[3] != 'S'))
{
TraceLog(WARNING, "[%s] This is not a valid raylib resource file", rresName);
@ -244,11 +244,11 @@ Sound LoadSoundFromRES(const char *rresName, int resId)
{
// Read number of resources embedded
fread(&numRes, sizeof(short), 1, rresFile);
for (int i = 0; i < numRes; i++)
{
fread(&infoHeader, sizeof(ResInfoHeader), 1, rresFile);
if (infoHeader.id == resId)
{
found = true;
@ -258,56 +258,56 @@ Sound LoadSoundFromRES(const char *rresName, int resId)
{
// TODO: Check data compression type
// NOTE: We suppose compression type 2 (DEFLATE - default)
// Reading SOUND parameters
Wave wave;
short sampleRate, bps;
char channels, reserved;
fread(&sampleRate, sizeof(short), 1, rresFile); // Sample rate (frequency)
fread(&bps, sizeof(short), 1, rresFile); // Bits per sample
fread(&channels, 1, 1, rresFile); // Channels (1 - mono, 2 - stereo)
fread(&reserved, 1, 1, rresFile); // <reserved>
wave.sampleRate = sampleRate;
wave.dataSize = infoHeader.srcSize;
wave.bitsPerSample = bps;
wave.channels = (short)channels;
unsigned char *data = malloc(infoHeader.size);
fread(data, infoHeader.size, 1, rresFile);
wave.data = DecompressData(data, infoHeader.size, infoHeader.srcSize);
free(data);
// Convert wave to Sound (OpenAL)
ALenum format = 0;
// The OpenAL format is worked out by looking at the number of channels and the bits per sample
if (wave.channels == 1)
if (wave.channels == 1)
{
if (wave.bitsPerSample == 8 ) format = AL_FORMAT_MONO8;
else if (wave.bitsPerSample == 16) format = AL_FORMAT_MONO16;
}
else if (wave.channels == 2)
}
else if (wave.channels == 2)
{
if (wave.bitsPerSample == 8 ) format = AL_FORMAT_STEREO8;
else if (wave.bitsPerSample == 16) format = AL_FORMAT_STEREO16;
}
// Create an audio source
ALuint source;
alGenSources(1, &source); // Generate pointer to audio source
alSourcef(source, AL_PITCH, 1);
alSourcef(source, AL_PITCH, 1);
alSourcef(source, AL_GAIN, 1);
alSource3f(source, AL_POSITION, 0, 0, 0);
alSource3f(source, AL_VELOCITY, 0, 0, 0);
alSourcei(source, AL_LOOPING, AL_FALSE);
// Convert loaded data to OpenAL buffer
//----------------------------------------
ALuint buffer;
@ -318,12 +318,12 @@ Sound LoadSoundFromRES(const char *rresName, int resId)
// Attach sound buffer to source
alSourcei(source, AL_BUFFER, buffer);
// Unallocate WAV data
UnloadWave(wave);
TraceLog(INFO, "[%s] Sound loaded successfully from resource, sample rate: %i", rresName, (int)sampleRate);
sound.source = source;
sound.buffer = buffer;
}
@ -344,18 +344,18 @@ Sound LoadSoundFromRES(const char *rresName, int resId)
case 4: break; // RAW: No parameters
default: break;
}
// Jump DATA to read next infoHeader
fseek(rresFile, infoHeader.size, SEEK_CUR);
}
}
}
}
fclose(rresFile);
}
if (!found) TraceLog(WARNING, "[%s] Required resource id [%i] could not be found in the raylib resource file", rresName, resId);
return sound;
}
@ -370,7 +370,7 @@ void UnloadSound(Sound sound)
void PlaySound(Sound sound)
{
alSourcePlay(sound.source); // Play the sound
//TraceLog(INFO, "Playing sound");
// Find the current position of the sound being played
@ -380,7 +380,7 @@ void PlaySound(Sound sound)
//
//int sampleRate;
//alGetBufferi(sound.buffer, AL_FREQUENCY, &sampleRate); // AL_CHANNELS, AL_BITS (bps)
//float seconds = (float)byteOffset / sampleRate; // Number of seconds since the beginning of the sound
//or
//float result;
@ -404,10 +404,10 @@ bool SoundIsPlaying(Sound sound)
{
bool playing = false;
ALint state;
alGetSourcei(sound.source, AL_SOURCE_STATE, &state);
if (state == AL_PLAYING) playing = true;
return playing;
}
@ -434,49 +434,49 @@ void PlayMusicStream(char *fileName)
{
// Stop current music, clean buffers, unload current stream
StopMusicStream();
// Open audio stream
currentMusic.stream = stb_vorbis_open_filename(fileName, NULL, NULL);
if (currentMusic.stream == NULL) TraceLog(WARNING, "[%s] Could not open ogg audio file", fileName);
else
{
// Get file info
stb_vorbis_info info = stb_vorbis_get_info(currentMusic.stream);
currentMusic.channels = info.channels;
currentMusic.sampleRate = info.sample_rate;
TraceLog(INFO, "[%s] Ogg sample rate: %i", fileName, info.sample_rate);
TraceLog(INFO, "[%s] Ogg channels: %i", fileName, info.channels);
TraceLog(INFO, "[%s] Temp memory required: %i", fileName, info.temp_memory_required);
if (info.channels == 2) currentMusic.format = AL_FORMAT_STEREO16;
else currentMusic.format = AL_FORMAT_MONO16;
currentMusic.loop = true; // We loop by default
musicEnabled = true;
// Create an audio source
alGenSources(1, &currentMusic.source); // Generate pointer to audio source
alSourcef(currentMusic.source, AL_PITCH, 1);
alSourcef(currentMusic.source, AL_PITCH, 1);
alSourcef(currentMusic.source, AL_GAIN, 1);
alSource3f(currentMusic.source, AL_POSITION, 0, 0, 0);
alSource3f(currentMusic.source, AL_VELOCITY, 0, 0, 0);
//alSourcei(currentMusic.source, AL_LOOPING, AL_TRUE); // ERROR: Buffers do not queue!
// Generate two OpenAL buffers
alGenBuffers(2, currentMusic.buffers);
// Fill buffers with music...
BufferMusicStream(currentMusic.buffers[0]);
BufferMusicStream(currentMusic.buffers[1]);
// Queue buffers and start playing
alSourceQueueBuffers(currentMusic.source, 2, currentMusic.buffers);
alSourcePlay(currentMusic.source);
// NOTE: Regularly, we must check if a buffer has been processed and refill it: MusicStreamUpdate()
currentMusic.totalSamplesLeft = stb_vorbis_stream_length_in_samples(currentMusic.stream) * currentMusic.channels;
@ -491,15 +491,15 @@ void StopMusicStream()
if (musicEnabled)
{
alSourceStop(currentMusic.source);
EmptyMusicStream(); // Empty music buffers
alDeleteSources(1, &currentMusic.source);
alDeleteBuffers(2, currentMusic.buffers);
stb_vorbis_close(currentMusic.stream);
}
musicEnabled = false;
}
@ -514,9 +514,9 @@ void PauseMusicStream()
bool MusicIsPlaying()
{
ALenum state;
alGetSourcei(currentMusic.source, AL_SOURCE_STATE, &state);
return (state == AL_PLAYING);
}
@ -530,7 +530,7 @@ void SetMusicVolume(float volume)
float GetMusicTimeLength()
{
float totalSeconds = stb_vorbis_stream_length_in_seconds(currentMusic.stream);
return totalSeconds;
}
@ -538,11 +538,11 @@ float GetMusicTimeLength()
float GetMusicTimePlayed()
{
int totalSamples = stb_vorbis_stream_length_in_samples(currentMusic.stream) * currentMusic.channels;
int samplesPlayed = totalSamples - currentMusic.totalSamplesLeft;
float secondsPlayed = (float)samplesPlayed / (currentMusic.sampleRate * currentMusic.channels);
return secondsPlayed;
}
@ -553,30 +553,30 @@ float GetMusicTimePlayed()
// Fill music buffers with new data from music stream
static bool BufferMusicStream(ALuint buffer)
{
short pcm[MUSIC_BUFFER_SIZE];
int size = 0; // Total size of data steamed (in bytes)
int streamedBytes = 0; // Bytes of data obtained in one samples get
short pcm[MUSIC_BUFFER_SIZE];
int size = 0; // Total size of data steamed (in bytes)
int streamedBytes = 0; // Bytes of data obtained in one samples get
bool active = true; // We can get more data from stream (not finished)
if (musicEnabled)
{
while (size < MUSIC_BUFFER_SIZE)
{
streamedBytes = stb_vorbis_get_samples_short_interleaved(currentMusic.stream, currentMusic.channels, pcm + size, MUSIC_BUFFER_SIZE - size);
if (streamedBytes > 0) size += (streamedBytes*currentMusic.channels);
else break;
}
TraceLog(DEBUG, "Streaming music data to buffer. Bytes streamed: %i", size);
}
if (size > 0)
if (size > 0)
{
alBufferData(buffer, currentMusic.format, pcm, size*sizeof(short), currentMusic.sampleRate);
currentMusic.totalSamplesLeft -= size;
}
else
@ -585,21 +585,21 @@ static bool BufferMusicStream(ALuint buffer)
TraceLog(WARNING, "No more data obtained from stream");
}
return active;
return active;
}
// Empty music buffers
static void EmptyMusicStream()
{
ALuint buffer = 0;
ALuint buffer = 0;
int queued = 0;
alGetSourcei(currentMusic.source, AL_BUFFERS_QUEUED, &queued);
while(queued > 0)
{
alSourceUnqueueBuffers(currentMusic.source, 1, &buffer);
queued--;
}
}
@ -610,12 +610,12 @@ extern void UpdateMusicStream()
ALuint buffer = 0;
ALint processed = 0;
bool active = true;
if (musicEnabled)
{
// Get the number of already processed buffers (if any)
alGetSourcei(currentMusic.source, AL_BUFFERS_PROCESSED, &processed);
while (processed > 0)
{
// Recover processed buffer for refill
@ -623,32 +623,32 @@ extern void UpdateMusicStream()
// Refill buffer
active = BufferMusicStream(buffer);
// If no more data to stream, restart music (if loop)
if ((!active) && (currentMusic.loop))
if ((!active) && (currentMusic.loop))
{
if (currentMusic.loop)
{
stb_vorbis_seek_start(currentMusic.stream);
currentMusic.totalSamplesLeft = stb_vorbis_stream_length_in_samples(currentMusic.stream) * currentMusic.channels;
active = BufferMusicStream(buffer);
}
}
// Add refilled buffer to queue again... don't let the music stop!
alSourceQueueBuffers(currentMusic.source, 1, &buffer);
if(alGetError() != AL_NO_ERROR) TraceLog(WARNING, "Ogg playing, error buffering data...");
processed--;
}
ALenum state;
alGetSourcei(currentMusic.source, AL_SOURCE_STATE, &state);
if ((state != AL_PLAYING) && active) alSourcePlay(currentMusic.source);
if (!active) StopMusicStream();
}
}
@ -678,16 +678,16 @@ static Wave LoadWAV(const char *fileName)
char subChunkID[4];
long subChunkSize;
} WaveData;
RiffHeader riffHeader;
WaveFormat waveFormat;
WaveData waveData;
Wave wave;
FILE *wavFile;
wavFile = fopen(fileName, "rb");
if (!wavFile)
{
TraceLog(WARNING, "[%s] Could not open WAV file", fileName);
@ -696,7 +696,7 @@ static Wave LoadWAV(const char *fileName)
{
// Read in the first chunk into the struct
fread(&riffHeader, sizeof(RiffHeader), 1, wavFile);
// Check for RIFF and WAVE tags
if (((riffHeader.chunkID[0] != 'R') || (riffHeader.chunkID[1] != 'I') || (riffHeader.chunkID[2] != 'F') || (riffHeader.chunkID[3] != 'F')) ||
((riffHeader.format[0] != 'W') || (riffHeader.format[1] != 'A') || (riffHeader.format[2] != 'V') || (riffHeader.format[3] != 'E')))
@ -707,7 +707,7 @@ static Wave LoadWAV(const char *fileName)
{
// Read in the 2nd chunk for the wave info
fread(&waveFormat, sizeof(WaveFormat), 1, wavFile);
// Check for fmt tag
if ((waveFormat.subChunkID[0] != 'f') || (waveFormat.subChunkID[1] != 'm') ||
(waveFormat.subChunkID[2] != 't') || (waveFormat.subChunkID[3] != ' '))
@ -718,10 +718,10 @@ static Wave LoadWAV(const char *fileName)
{
// Check for extra parameters;
if (waveFormat.subChunkSize > 16) fseek(wavFile, sizeof(short), SEEK_CUR);
// Read in the the last byte of data before the sound file
fread(&waveData, sizeof(WaveData), 1, wavFile);
// Check for data tag
if ((waveData.subChunkID[0] != 'd') || (waveData.subChunkID[1] != 'a') ||
(waveData.subChunkID[2] != 't') || (waveData.subChunkID[3] != 'a'))
@ -731,17 +731,17 @@ static Wave LoadWAV(const char *fileName)
else
{
// Allocate memory for data
wave.data = (unsigned char *)malloc(sizeof(unsigned char) * waveData.subChunkSize);
wave.data = (unsigned char *)malloc(sizeof(unsigned char) * waveData.subChunkSize);
// Read in the sound data into the soundData variable
fread(wave.data, waveData.subChunkSize, 1, wavFile);
// Now we set the variables that we need later
wave.dataSize = waveData.subChunkSize;
wave.sampleRate = waveFormat.sampleRate;
wave.channels = waveFormat.numChannels;
wave.bitsPerSample = waveFormat.bitsPerSample;
TraceLog(INFO, "[%s] Wave file loaded successfully", fileName);
}
}
@ -749,7 +749,7 @@ static Wave LoadWAV(const char *fileName)
fclose(wavFile);
}
return wave;
}
@ -757,42 +757,42 @@ static Wave LoadWAV(const char *fileName)
static Wave LoadOGG(char *fileName)
{
Wave wave;
stb_vorbis *oggFile = stb_vorbis_open_filename(fileName, NULL, NULL);
stb_vorbis_info info = stb_vorbis_get_info(oggFile);
wave.sampleRate = info.sample_rate;
wave.bitsPerSample = 16;
wave.channels = info.channels;
TraceLog(DEBUG, "[%s] Ogg sample rate: %i", fileName, info.sample_rate);
TraceLog(DEBUG, "[%s] Ogg channels: %i", fileName, info.channels);
int totalSamplesLength = (stb_vorbis_stream_length_in_samples(oggFile) * info.channels);
wave.dataSize = totalSamplesLength*sizeof(short); // Size must be in bytes
TraceLog(DEBUG, "[%s] Samples length: %i", fileName, totalSamplesLength);
float totalSeconds = stb_vorbis_stream_length_in_seconds(oggFile);
TraceLog(DEBUG, "[%s] Total seconds: %f", 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;
TraceLog(DEBUG, "[%s] Total samples calculated: %i", fileName, totalSamples);
//short *data
//short *data
wave.data = malloc(sizeof(short)*totalSamplesLength);
int samplesObtained = stb_vorbis_get_samples_short_interleaved(oggFile, info.channels, wave.data, totalSamplesLength);
TraceLog(DEBUG, "[%s] Samples obtained: %i", fileName, samplesObtained);
stb_vorbis_close(oggFile);
return wave;
}

View File

@ -3,20 +3,20 @@
* raylib.core
*
* Basic functions to manage Windows, OpenGL context and Input
*
* Uses external lib:
*
* Uses external lib:
* GLFW3 - Window, context and Input management (static lib version)
*
* Copyright (c) 2013 Ramon Santamaria (Ray San - raysan@raysanweb.com)
*
* 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.
*
* Permission is granted to anyone to use this software for any purpose, including commercial
* Permission is granted to anyone to use this software for any purpose, including commercial
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* in the product documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
@ -121,11 +121,11 @@ void InitWindow(int width, int height, const char *title)
void InitWindowEx(int width, int height, const char* title, bool resizable, const char *cursorImage)
{
glfwSetErrorCallback(ErrorCallback);
if (!glfwInit()) TraceLog(ERROR, "Failed to initialize GLFW");
//glfwDefaultWindowHints() // Set default windows hints
if (!resizable) glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); // Avoid window being resizable
#ifdef USE_OPENGL_33
@ -137,20 +137,20 @@ void InitWindowEx(int width, int height, const char* title, bool resizable, cons
#endif
window = glfwCreateWindow(width, height, title, NULL, NULL);
windowWidth = width;
windowHeight = height;
windowTitle = title;
if (!window)
{
glfwTerminate();
TraceLog(ERROR, "Failed to initialize Window");
}
glfwSetWindowSizeCallback(window, WindowSizeCallback);
glfwSetCursorEnterCallback(window, CursorEnterCallback);
glfwMakeContextCurrent(window);
glfwSetKeyCallback(window, KeyCallback);
glfwSetScrollCallback(window, ScrollCallback);
@ -158,29 +158,29 @@ void InitWindowEx(int width, int height, const char* title, bool resizable, cons
// If not set, swap interval uses GPU v-sync configuration
// Framerate can be setup using SetTargetFPS()
//------------------------------------------------------
//------------------------------------------------------
#if defined(USE_OPENGL_33) || defined(USE_OPENGL_ES2)
rlglInit(); // Init rlgl
#endif
//------------------------------------------------------
int fbWidth, fbHeight;
glfwGetFramebufferSize(window, &fbWidth, &fbHeight); // Get framebuffer size of current window
//------------------------------------------------------
//------------------------------------------------------
rlglInitGraphicsDevice(fbWidth, fbHeight);
//------------------------------------------------------
previousTime = glfwGetTime();
LoadDefaultFont(); // NOTE: External function (defined in module: text)
if (cursorImage != NULL) SetCustomCursor(cursorImage);
srand(time(NULL)); // Initialize random seed
ClearBackground(RAYWHITE); // Default background color for raylib games :P
// raylib logo appearing animation
if (showLogo)
{
@ -193,7 +193,7 @@ void InitWindowEx(int width, int height, const char* title, bool resizable, cons
void CloseWindow()
{
UnloadDefaultFont();
//------------------------------------------------------
#if defined(USE_OPENGL_33) || defined(USE_OPENGL_ES2)
rlglClose(); // De-init rlgl
@ -208,9 +208,9 @@ void CloseWindow()
void SetCustomCursor(const char *cursorImage)
{
if (customCursor) UnloadTexture(cursor);
cursor = LoadTexture(cursorImage);
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
customCursor = true;
}
@ -231,14 +231,14 @@ bool WindowShouldClose()
// Fullscreen toggle (by default F11)
void ToggleFullscreen()
{
if (glfwGetKey(window, GLFW_KEY_F11))
if (glfwGetKey(window, GLFW_KEY_F11))
{
fullscreen = !fullscreen; // Toggle fullscreen flag
UnloadDefaultFont();
glfwDestroyWindow(window); // Destroy the current window (we will recreate it!)
// TODO: WARNING! All loaded resources are lost, we loose Context!
// NOTE: Window aspect ratio is always windowWidth / windowHeight
@ -248,7 +248,7 @@ void ToggleFullscreen()
//const GLFWvidmode *mode = glfwGetVideoMode(glfwGetPrimaryMonitor());
//windowWidth = mode->width;
//windowHeight = mode->height;
window = glfwCreateWindow(windowWidth, windowHeight, windowTitle, glfwGetPrimaryMonitor(), NULL); // Fullscreen mode
}
else window = glfwCreateWindow(windowWidth, windowHeight, windowTitle, NULL, NULL);
@ -258,7 +258,7 @@ void ToggleFullscreen()
glfwTerminate();
TraceLog(ERROR, "Failed to initialize Window when switching fullscreen mode");
}
glfwMakeContextCurrent(window);
glfwSetKeyCallback(window, KeyCallback);
@ -266,7 +266,7 @@ void ToggleFullscreen()
glfwGetFramebufferSize(window, &fbWidth, &fbHeight); // Get framebuffer size of current window
rlglInitGraphicsDevice(fbWidth, fbHeight);
LoadDefaultFont();
}
}
@ -275,9 +275,9 @@ void ToggleFullscreen()
void ClearBackground(Color color)
{
if ((color.r != background.r) || (color.g != background.g) || (color.b != background.b) || (color.a != background.a))
{
{
rlClearColor(color.r, color.g, color.b, color.a);
background = color;
}
}
@ -290,7 +290,7 @@ void BeginDrawing()
previousTime = currentTime;
rlClearScreenBuffers();
rlLoadIdentity(); // Reset current matrix (MODELVIEW)
//#ifdef USE_OPENGL_11
@ -309,18 +309,18 @@ void EndDrawing()
rlglDraw(); // Draw Buffers
#endif
//------------------------------------------------------
glfwSwapBuffers(window); // Swap back and front buffers
glfwPollEvents(); // Register keyboard/mouse events
UpdateMusicStream(); // NOTE: Function checks if music is enabled
currentTime = glfwGetTime();
drawTime = currentTime - previousTime;
previousTime = currentTime;
frameTime = updateTime + drawTime;
double extraTime = 0;
while (frameTime < targetTime)
@ -343,20 +343,20 @@ void Begin3dMode(Camera camera)
//------------------------------------------------------
rlMatrixMode(RL_PROJECTION); // Switch to projection matrix
rlPushMatrix(); // Save previous matrix, which contains the settings for the 2d ortho projection
rlLoadIdentity(); // Reset current matrix (PROJECTION)
// Setup perspective projection
float aspect = (GLfloat)windowWidth/(GLfloat)windowHeight;
double top = 0.1f*tan(45.0f*PI / 360.0);
double right = top*aspect;
rlFrustum(-right, right, -top, top, 0.1f, 100.0f);
rlMatrixMode(RL_MODELVIEW); // Switch back to modelview matrix
rlLoadIdentity(); // Reset current matrix (MODELVIEW)
// Setup Camera view
Matrix matLookAt = MatrixLookAt(camera.position, camera.target, camera.up);
rlMultMatrixf(GetMatrixVector(matLookAt)); // Multiply MODELVIEW matrix by view matrix (camera)
@ -373,10 +373,10 @@ void End3dMode()
rlMatrixMode(RL_PROJECTION); // Switch to projection matrix
rlPopMatrix(); // Restore previous matrix (PROJECTION) from matrix stack
rlMatrixMode(RL_MODELVIEW); // Get back to modelview matrix
rlLoadIdentity(); // Reset current matrix (MODELVIEW)
//rlTranslatef(0.375, 0.375, 0); // HACK to ensure pixel-perfect drawing on OpenGL (after exiting 3D mode)
}
@ -384,7 +384,7 @@ void End3dMode()
void SetTargetFPS(int fps)
{
targetTime = 1 / (float)fps;
TraceLog(INFO, "Target time per frame: %02.03f milliseconds", (float)targetTime*1000);
}
@ -401,7 +401,7 @@ float GetFrameTime()
// so we round it before before passing around to be used
// NOTE: There are still problems with high framerates (>500fps)
double roundedFrameTime = round(frameTime*10000) / 10000;
return (float)roundedFrameTime; // Time in seconds to run a frame
}
@ -414,7 +414,7 @@ Color GetColor(int hexValue)
color.g = (unsigned char)(hexValue >> 16) & 0xFF;
color.b = (unsigned char)(hexValue >> 8) & 0xFF;
color.a = (unsigned char)hexValue & 0xFF;
return color;
}
@ -458,7 +458,7 @@ void ShowLogo()
// Detect if a key has been pressed once
bool IsKeyPressed(int key)
{
{
bool pressed = false;
currentKeyState[key] = IsKeyDown(key);
@ -469,7 +469,7 @@ bool IsKeyPressed(int key)
previousKeyState[key] = currentKeyState[key];
}
else pressed = false;
return pressed;
}
@ -482,9 +482,9 @@ bool IsKeyDown(int key)
// Detect if a key has been released once
bool IsKeyReleased(int key)
{
{
bool released = false;
currentKeyState[key] = IsKeyUp(key);
if (currentKeyState[key] != previousKeyState[key])
@ -493,7 +493,7 @@ bool IsKeyReleased(int key)
previousKeyState[key] = currentKeyState[key];
}
else released = false;
return released;
}
@ -517,7 +517,7 @@ bool IsMouseButtonPressed(int button)
previousMouseState[button] = currentMouseState[button];
}
else pressed = false;
return pressed;
}
@ -541,7 +541,7 @@ bool IsMouseButtonReleased(int button)
previousMouseState[button] = currentMouseState[button];
}
else released = false;
return released;
}
@ -557,7 +557,7 @@ int GetMouseX()
{
double mouseX;
double mouseY;
glfwGetCursorPos(window, &mouseX, &mouseY);
return (int)mouseX;
@ -568,7 +568,7 @@ int GetMouseY()
{
double mouseX;
double mouseY;
glfwGetCursorPos(window, &mouseX, &mouseY);
return (int)mouseY;
@ -579,9 +579,9 @@ Vector2 GetMousePosition()
{
double mouseX;
double mouseY;
glfwGetCursorPos(window, &mouseX, &mouseY);
Vector2 position = { (float)mouseX, (float)mouseY };
return position;
@ -593,7 +593,7 @@ int GetMouseWheelMove()
previousMouseWheelY = currentMouseWheelY;
currentMouseWheelY = 0;
return previousMouseWheelY;
}
@ -601,7 +601,7 @@ int GetMouseWheelMove()
bool IsGamepadAvailable(int gamepad)
{
int result = glfwJoystickPresent(gamepad);
if (result == 1) return true;
else return false;
}
@ -610,20 +610,20 @@ bool IsGamepadAvailable(int gamepad)
Vector2 GetGamepadMovement(int gamepad)
{
Vector2 vec = { 0, 0 };
const float *axes;
int axisCount;
axes = glfwGetJoystickAxes(gamepad, &axisCount);
if (axisCount >= 2)
{
vec.x = axes[0]; // Left joystick X
vec.x = axes[0]; // Left joystick X
vec.y = axes[1]; // Left joystick Y
//vec.x = axes[2]; // Right joystick X
//vec.x = axes[3]; // Right joystick Y
}
}
return vec;
}
@ -641,7 +641,7 @@ bool IsGamepadButtonPressed(int gamepad, int button)
previousGamepadState[button] = currentGamepadState[button];
}
else pressed = false;
return pressed;
}
@ -649,9 +649,9 @@ bool IsGamepadButtonDown(int gamepad, int button)
{
const unsigned char* buttons;
int buttonsCount;
buttons = glfwGetJoystickButtons(gamepad, &buttonsCount);
if ((buttons != NULL) && (buttons[button] == GLFW_PRESS))
{
return true;
@ -672,7 +672,7 @@ bool IsGamepadButtonReleased(int gamepad, int button)
previousGamepadState[button] = currentGamepadState[button];
}
else released = false;
return released;
}
@ -680,9 +680,9 @@ bool IsGamepadButtonUp(int gamepad, int button)
{
const unsigned char* buttons;
int buttonsCount;
buttons = glfwGetJoystickButtons(gamepad, &buttonsCount);
if ((buttons != NULL) && (buttons[button] == GLFW_RELEASE))
{
return true;
@ -712,7 +712,7 @@ static void KeyCallback(GLFWwindow* window, int key, int scancode, int action, i
if (key == exitKey && action == GLFW_PRESS)
{
glfwSetWindowShouldClose(window, GL_TRUE);
// NOTE: Before closing window, while loop must be left!
}
else if (key == GLFW_KEY_F11 && action == GLFW_PRESS)
@ -739,11 +739,11 @@ static void WindowSizeCallback(GLFWwindow* window, int width, int height)
// If window is resized, graphics device is re-initialized (but only ortho mode)
rlglInitGraphicsDevice(fbWidth, fbHeight);
// Window size must be updated to be used on 3D mode to get new aspect ratio (Begin3dMode())
windowWidth = fbWidth;
windowHeight = fbHeight;
// Background must be also re-cleared
rlClearColor(background.r, background.g, background.b, background.a);
}
@ -767,7 +767,7 @@ static void TakeScreenshot()
free(imgData);
shotNum++;
TraceLog(INFO, "[%s] Screenshot taken!", buffer);
}
@ -775,20 +775,20 @@ static void LogoAnimation()
{
int logoPositionX = windowWidth/2 - 128;
int logoPositionY = windowHeight/2 - 128;
int framesCounter = 0;
int lettersCount = 0;
int topSideRecWidth = 16;
int leftSideRecHeight = 16;
int bottomSideRecWidth = 16;
int rightSideRecHeight = 16;
char raylib[8] = " "; // raylib text array, max 8 letters
int state = 0; // Tracking animation states (State Machine)
float alpha = 1.0; // Useful for fading
while (!WindowShouldClose() && (state != 4)) // Detect window close button or ESC key
{
// Update
@ -796,9 +796,9 @@ static void LogoAnimation()
if (state == 0) // State 0: Small box blinking
{
framesCounter++;
if (framesCounter == 84)
{
{
state = 1;
framesCounter = 0; // Reset counter... will be used later...
}
@ -807,26 +807,26 @@ static void LogoAnimation()
{
topSideRecWidth += 4;
leftSideRecHeight += 4;
if (topSideRecWidth == 256) state = 2;
}
else if (state == 2) // State 2: Bottom and right bars growing
{
bottomSideRecWidth += 4;
rightSideRecHeight += 4;
if (bottomSideRecWidth == 256) state = 3;
}
else if (state == 3) // State 3: Letters appearing (one by one)
{
framesCounter++;
if (framesCounter/12) // Every 12 frames, one more letter!
{
{
lettersCount++;
framesCounter = 0;
}
switch (lettersCount)
{
case 1: raylib[0] = 'r'; break;
@ -837,11 +837,11 @@ static void LogoAnimation()
case 6: raylib[5] = 'b'; break;
default: break;
}
if (lettersCount >= 10) // When all letters have appeared, just fade out everything
{
alpha -= 0.02;
if (alpha <= 0)
{
alpha = 0;
@ -850,11 +850,11 @@ static void LogoAnimation()
}
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
if (state == 0)
{
if ((framesCounter/12)%2) DrawRectangle(logoPositionX, logoPositionY, 16, 16, BLACK);
@ -868,7 +868,7 @@ static void LogoAnimation()
{
DrawRectangle(logoPositionX, logoPositionY, topSideRecWidth, 16, BLACK);
DrawRectangle(logoPositionX, logoPositionY, 16, leftSideRecHeight, BLACK);
DrawRectangle(logoPositionX + 240, logoPositionY, 16, rightSideRecHeight, BLACK);
DrawRectangle(logoPositionX, logoPositionY + 240, bottomSideRecWidth, 16, BLACK);
}
@ -876,15 +876,15 @@ static void LogoAnimation()
{
DrawRectangle(logoPositionX, logoPositionY, topSideRecWidth, 16, Fade(BLACK, alpha));
DrawRectangle(logoPositionX, logoPositionY + 16, 16, leftSideRecHeight - 32, Fade(BLACK, alpha));
DrawRectangle(logoPositionX + 240, logoPositionY + 16, 16, rightSideRecHeight - 32, Fade(BLACK, alpha));
DrawRectangle(logoPositionX, logoPositionY + 240, bottomSideRecWidth, 16, Fade(BLACK, alpha));
DrawRectangle(windowWidth/2 - 112, windowHeight/2 - 112, 224, 224, Fade(RAYWHITE, alpha));
DrawText(raylib, windowWidth/2 - 44, windowHeight/2 + 48, 50, Fade(BLACK, alpha));
}
EndDrawing();
//----------------------------------------------------------------------------------
}

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
/*********************************************************************************************
*
*
* raylib 1.1 (www.raylib.com)
*
*
* A simple and easy-to-use library to learn videogames programming
*
* Features:
@ -14,7 +14,7 @@
* Basic 3d support for Shapes, Models, Heightmaps and Billboards
* Powerful math module for Vector and Matrix operations [raymath]
* Audio loading and playing with streaming support
*
*
* Used external libs:
* GLFW3 (www.glfw.org) for window/context management and input
* GLEW for OpenGL extensions loading (3.3+ and ES2)
@ -33,19 +33,19 @@
*
* -- LICENSE (raylib v1.1, April 2014) --
*
* raylib is licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* raylib is licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software:
*
*
* Copyright (c) 2013 Ramon Santamaria (Ray San - raysan@raysanweb.com)
*
* 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.
*
* Permission is granted to anyone to use this software for any purpose, including commercial
* Permission is granted to anyone to use this software for any purpose, including commercial
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* in the product documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
@ -354,7 +354,7 @@ void DrawTextureV(Texture2D texture, Vector2 position, Color tint);
void DrawTextureEx(Texture2D texture, Vector2 position, float rotation, float scale, Color tint); // Draw a Texture2D with extended parameters
void DrawTextureRec(Texture2D texture, Rectangle sourceRec, Vector2 position, Color tint); // Draw a part of a texture defined by a rectangle
void DrawTexturePro(Texture2D texture, Rectangle sourceRec, Rectangle destRec, Vector2 origin, // Draw a part of a texture defined by a rectangle with 'pro' parameters
float rotation, Color tint);
float rotation, Color tint);
//------------------------------------------------------------------------------------
// Font Loading and Text Drawing Functions (Module: text)
@ -406,7 +406,7 @@ void DrawModelEx(Model model, Vector3 position, Vector3 rotation, Vector3 scale,
void DrawModelWires(Model model, Vector3 position, float scale, Color color); // Draw a model wires (with texture if set)
void DrawBillboard(Camera camera, Texture2D texture, Vector3 center, float size, Color tint); // Draw a billboard texture
void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle sourceRec, Vector3 center, float size, Color tint); // Draw a billboard texture defined by sourceRec
void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle sourceRec, Vector3 center, float size, Color tint); // Draw a billboard texture defined by sourceRec
//------------------------------------------------------------------------------------
// Audio Loading and Playing Functions (Module: audio)

View File

@ -5,15 +5,15 @@
* Some useful functions to work with Vector3, Matrix and Quaternions
*
* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
*
* 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.
*
* Permission is granted to anyone to use this software for any purpose, including commercial
* Permission is granted to anyone to use this software for any purpose, including commercial
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* in the product documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
@ -51,7 +51,7 @@ Vector3 VectorAdd(Vector3 v1, Vector3 v2)
result.x = v1.x + v2.x;
result.y = v1.y + v2.y;
result.z = v1.z + v2.z;
return result;
}
@ -63,7 +63,7 @@ Vector3 VectorSubtract(Vector3 v1, Vector3 v2)
result.x = v1.x - v2.x;
result.y = v1.y - v2.y;
result.z = v1.z - v2.z;
return result;
}
@ -75,7 +75,7 @@ Vector3 VectorCrossProduct(Vector3 v1, Vector3 v2)
result.x = v1.y*v2.z - v1.z*v2.y;
result.y = v1.z*v2.x - v1.x*v2.z;
result.z = v1.x*v2.y - v1.y*v2.x;
return result;
}
@ -83,23 +83,23 @@ Vector3 VectorCrossProduct(Vector3 v1, Vector3 v2)
Vector3 VectorPerpendicular(Vector3 v)
{
Vector3 result;
float min = fabs(v.x);
Vector3 cardinalAxis = {1.0, 0.0, 0.0};
if (fabs(v.y) < min)
if (fabs(v.y) < min)
{
min = fabs(v.y);
cardinalAxis = (Vector3){0.0, 1.0, 0.0};
}
if(fabs(v.z) < min)
if(fabs(v.z) < min)
{
cardinalAxis = (Vector3){0.0, 0.0, 1.0};
}
result = VectorCrossProduct(v, cardinalAxis);
return result;
}
@ -107,9 +107,9 @@ Vector3 VectorPerpendicular(Vector3 v)
float VectorDotProduct(Vector3 v1, Vector3 v2)
{
float result;
result = v1.x*v2.x + v1.y*v2.y + v1.z*v2.z;
return result;
}
@ -117,9 +117,9 @@ float VectorDotProduct(Vector3 v1, Vector3 v2)
float VectorLength(const Vector3 v)
{
float length;
length = sqrt(v.x*v.x + v.y*v.y + v.z*v.z);
return length;
}
@ -145,11 +145,11 @@ void VectorNormalize(Vector3 *v)
float length, ilength;
length = VectorLength(*v);
if (length == 0) length = 1;
ilength = 1.0/length;
v->x *= ilength;
v->y *= ilength;
v->z *= ilength;
@ -159,13 +159,13 @@ void VectorNormalize(Vector3 *v)
float VectorDistance(Vector3 v1, Vector3 v2)
{
float result;
float dx = v2.x - v1.x;
float dy = v2.y - v1.y;
float dz = v2.z - v1.z;
result = sqrt(dx*dx + dy*dy + dz*dz);
return result;
}
@ -173,7 +173,7 @@ float VectorDistance(Vector3 v1, Vector3 v2)
Vector3 VectorLerp(Vector3 v1, Vector3 v2, float amount)
{
Vector3 result;
result.x = v1.x + amount * (v2.x - v1.x);
result.y = v1.y + amount * (v2.y - v1.y);
result.z = v1.z + amount * (v2.z - v1.z);
@ -187,11 +187,11 @@ Vector3 VectorReflect(Vector3 vector, Vector3 normal)
// I is the original vector
// N is the normal of the incident plane
// R = I - (2 * N * ( DotProduct[ I,N] ))
Vector3 result;
float dotProduct = VectorDotProduct(vector, normal);
result.x = vector.x - (2.0 * normal.x) * dotProduct;
result.y = vector.y - (2.0 * normal.y) * dotProduct;
result.z = vector.z - (2.0 * normal.z) * dotProduct;
@ -203,11 +203,11 @@ Vector3 VectorReflect(Vector3 vector, Vector3 normal)
void VectorTransform(Vector3 *v, Matrix mat)
{
float x = v->x;
float y = v->y;
float y = v->y;
float z = v->z;
//MatrixTranspose(&mat);
v->x = mat.m0*x + mat.m4*y + mat.m8*z + mat.m12;
v->y = mat.m1*x + mat.m5*y + mat.m9*z + mat.m13;
v->z = mat.m2*x + mat.m6*y + mat.m10*z + mat.m14;
@ -217,7 +217,7 @@ void VectorTransform(Vector3 *v, Matrix mat)
Vector3 VectorZero()
{
Vector3 zero = { 0.0, 0.0, 0.0 };
return zero;
}
@ -229,7 +229,7 @@ Vector3 VectorZero()
float *GetMatrixVector(Matrix mat)
{
static float vector[16];
vector[0] = mat.m0;
vector[1] = mat.m4;
vector[2] = mat.m8;
@ -246,7 +246,7 @@ float *GetMatrixVector(Matrix mat)
vector[13] = mat.m7;
vector[14] = mat.m11;
vector[15] = mat.m15;
return vector;
}
@ -267,7 +267,7 @@ float MatrixDeterminant(Matrix mat)
a30*a11*a02*a23 - a10*a31*a02*a23 - a30*a01*a12*a23 + a00*a31*a12*a23 +
a10*a01*a32*a23 - a00*a11*a32*a23 - a20*a11*a02*a33 + a10*a21*a02*a33 +
a20*a01*a12*a33 - a00*a21*a12*a33 - a10*a01*a22*a33 + a00*a11*a22*a33;
return result;
}
@ -298,7 +298,7 @@ void MatrixTranspose(Matrix *mat)
temp.m13 = mat->m7;
temp.m14 = mat->m11;
temp.m15 = mat->m15;
*mat = temp;
}
@ -306,13 +306,13 @@ void MatrixTranspose(Matrix *mat)
void MatrixInvert(Matrix *mat)
{
Matrix temp;
// Cache the matrix values (speed optimization)
float a00 = mat->m0, a01 = mat->m1, a02 = mat->m2, a03 = mat->m3;
float a10 = mat->m4, a11 = mat->m5, a12 = mat->m6, a13 = mat->m7;
float a20 = mat->m8, a21 = mat->m9, a22 = mat->m10, a23 = mat->m11;
float a30 = mat->m12, a31 = mat->m13, a32 = mat->m14, a33 = mat->m15;
float b00 = a00*a11 - a01*a10;
float b01 = a00*a12 - a02*a10;
float b02 = a00*a13 - a03*a10;
@ -325,12 +325,12 @@ void MatrixInvert(Matrix *mat)
float b09 = a21*a32 - a22*a31;
float b10 = a21*a33 - a23*a31;
float b11 = a22*a33 - a23*a32;
// Calculate the invert determinant (inlined to avoid double-caching)
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.m1 = (-a01*b11 + a02*b10 - a03*b09)*invDet;
temp.m2 = (a31*b05 - a32*b04 + a33*b03)*invDet;
@ -347,9 +347,9 @@ void MatrixInvert(Matrix *mat)
temp.m13 = (a00*b09 - a01*b07 + a02*b06)*invDet;
temp.m14 = (-a30*b03 + a31*b01 - a32*b00)*invDet;
temp.m15 = (a20*b03 - a21*b01 + a22*b00)*invDet;
PrintMatrix(temp);
*mat = temp;
}
@ -357,7 +357,7 @@ void MatrixInvert(Matrix *mat)
void MatrixNormalize(Matrix *mat)
{
float det = MatrixDeterminant(*mat);
mat->m0 /= det;
mat->m1 /= det;
mat->m2 /= det;
@ -388,7 +388,7 @@ Matrix MatrixIdentity()
Matrix MatrixAdd(Matrix left, Matrix right)
{
Matrix result = MatrixIdentity();
result.m0 = left.m0 + right.m0;
result.m1 = left.m1 + right.m1;
result.m2 = left.m2 + right.m2;
@ -413,7 +413,7 @@ Matrix MatrixAdd(Matrix left, Matrix right)
Matrix MatrixSubstract(Matrix left, Matrix right)
{
Matrix result = MatrixIdentity();
result.m0 = left.m0 - right.m0;
result.m1 = left.m1 - right.m1;
result.m2 = left.m2 - right.m2;
@ -444,36 +444,36 @@ Matrix MatrixTranslate(float x, float y, float z)
0, 1, 0, 0
0, 0, 1, 0
x, y, z, 1
Is the correct Translation Matrix. Why? Opengl Uses column-major matrix ordering.
Which is the Transpose of the Matrix you initially presented, which is in row-major ordering.
Row major is used in most math text-books and also DirectX, so it is a common
Is the correct Translation Matrix. Why? Opengl Uses column-major matrix ordering.
Which is the Transpose of the Matrix you initially presented, which is in row-major ordering.
Row major is used in most math text-books and also DirectX, so it is a common
point of confusion for those new to OpenGL.
* matrix notation used in opengl documentation does not describe in-memory layout for OpenGL matrices
Translation matrix should be laid out in memory like this:
{ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, trabsX, transY, transZ, 1 }
9.005 Are OpenGL matrices column-major or row-major?
For programming purposes, OpenGL matrices are 16-value arrays with base vectors laid out
contiguously in memory. The translation components occupy the 13th, 14th, and 15th elements
of the 16-element matrix, where indices are numbered from 1 to 16 as described in section
For programming purposes, OpenGL matrices are 16-value arrays with base vectors laid out
contiguously in memory. The translation components occupy the 13th, 14th, and 15th elements
of the 16-element matrix, where indices are numbered from 1 to 16 as described in section
2.11.2 of the OpenGL 2.1 Specification.
Column-major versus row-major is purely a notational convention. Note that post-multiplying
with column-major matrices produces the same result as pre-multiplying with row-major matrices.
The OpenGL Specification and the OpenGL Reference Manual both use column-major notation.
Column-major versus row-major is purely a notational convention. Note that post-multiplying
with column-major matrices produces the same result as pre-multiplying with row-major matrices.
The OpenGL Specification and the OpenGL Reference Manual both use column-major notation.
You can use any notation, as long as it's clearly stated.
Sadly, the use of column-major format in the spec and blue book has resulted in endless confusion
in the OpenGL programming community. Column-major notation suggests that matrices
Sadly, the use of column-major format in the spec and blue book has resulted in endless confusion
in the OpenGL programming community. Column-major notation suggests that matrices
are not laid out in memory as a programmer would expect.
*/
Matrix result = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, x, y, z, 1 };
return result;
}
@ -482,50 +482,50 @@ Matrix MatrixTranslate(float x, float y, float z)
Matrix MatrixRotate(float angleX, float angleY, float angleZ)
{
Matrix result;
Matrix rotX = MatrixRotateX(angleX);
Matrix rotY = MatrixRotateY(angleY);
Matrix rotZ = MatrixRotateZ(angleZ);
result = MatrixMultiply(MatrixMultiply(rotX, rotY), rotZ);
return result;
}
// Create rotation matrix from axis and angle
// TODO: Test this function
Matrix MatrixFromAxisAngle(Vector3 axis, float angle)
Matrix MatrixFromAxisAngle(Vector3 axis, float angle)
{
Matrix result;
Matrix mat = MatrixIdentity();
float x = axis.x, y = axis.y, z = axis.z;
float length = sqrt(x*x + y*y + z*z);
if ((length != 1) && (length != 0))
{
length = 1 / length;
x *= length;
y *= length;
x *= length;
y *= length;
z *= length;
}
float s = sin(angle);
float c = cos(angle);
float t = 1-c;
// Cache some matrix values (speed optimization)
float a00 = mat.m0, a01 = mat.m1, a02 = mat.m2, a03 = mat.m3;
float a10 = mat.m4, a11 = mat.m5, a12 = mat.m6, a13 = mat.m7;
float a20 = mat.m8, a21 = mat.m9, a22 = mat.m10, a23 = mat.m11;
// Construct the elements of the rotation matrix
float b00 = x*x*t + c, b01 = y*x*t + z*s, b02 = z*x*t - y*s;
float b10 = x*y*t - z*s, b11 = y*y*t + c, b12 = z*y*t + x*s;
float b20 = x*z*t + y*s, b21 = y*z*t - x*s, b22 = z*z*t + c;
// Perform rotation-specific matrix multiplication
result.m0 = a00*b00 + a10*b01 + a20*b02;
result.m1 = a01*b00 + a11*b01 + a21*b02;
@ -543,7 +543,7 @@ Matrix MatrixFromAxisAngle(Vector3 axis, float angle)
result.m13 = mat.m13;
result.m14 = mat.m14;
result.m15 = mat.m15;
return result;
};
@ -552,7 +552,7 @@ Matrix MatrixFromAxisAngle(Vector3 axis, float angle)
Matrix MatrixFromAxisAngle2(Vector3 axis, float angle)
{
Matrix result;
VectorNormalize(&axis);
float axisX = axis.x, axisY = axis.y, axisZ = axis.y;
@ -589,7 +589,7 @@ Matrix MatrixFromAxisAngle2(Vector3 axis, float angle)
result.m13 = 0;
result.m14 = 0;
result.m15 = 1;
return result;
}
@ -597,14 +597,14 @@ Matrix MatrixFromAxisAngle2(Vector3 axis, float angle)
Matrix MatrixFromQuaternion(Quaternion q)
{
Matrix result = MatrixIdentity();
Vector3 axis;
float angle;
QuaternionToAxisAngle(q, &axis, &angle);
result = MatrixFromAxisAngle2(axis, angle);
return result;
}
@ -612,10 +612,10 @@ Matrix MatrixFromQuaternion(Quaternion q)
Matrix MatrixRotateX(float angle)
{
Matrix result = MatrixIdentity();
float cosres = (float)cos(angle);
float sinres = (float)sin(angle);
result.m5 = cosres;
result.m6 = -sinres;
result.m9 = sinres;
@ -628,10 +628,10 @@ Matrix MatrixRotateX(float angle)
Matrix MatrixRotateY(float angle)
{
Matrix result = MatrixIdentity();
float cosres = (float)cos(angle);
float sinres = (float)sin(angle);
result.m0 = cosres;
result.m2 = sinres;
result.m8 = -sinres;
@ -644,10 +644,10 @@ Matrix MatrixRotateY(float angle)
Matrix MatrixRotateZ(float angle)
{
Matrix result = MatrixIdentity();
float cosres = (float)cos(angle);
float sinres = (float)sin(angle);
result.m0 = cosres;
result.m1 = -sinres;
result.m4 = sinres;
@ -669,7 +669,7 @@ Matrix MatrixScale(float x, float y, float z)
Matrix MatrixTransform(Vector3 translation, Vector3 rotation, Vector3 scale)
{
Matrix result = MatrixIdentity();
Matrix mRotation = MatrixRotate(rotation.x, rotation.y, rotation.z);
Matrix mScale = MatrixScale(scale.x, scale.y, scale.z);
Matrix mTranslate = MatrixTranslate(translation.x, translation.y, translation.z);
@ -690,12 +690,12 @@ Matrix MatrixMultiply(Matrix left, Matrix right)
float a10 = left.m4, a11 = left.m5, a12 = left.m6, a13 = left.m7;
float a20 = left.m8, a21 = left.m9, a22 = left.m10, a23 = left.m11;
float a30 = left.m12, a31 = left.m13, a32 = left.m14, a33 = left.m15;
float b00 = right.m0, b01 = right.m1, b02 = right.m2, b03 = right.m3;
float b10 = right.m4, b11 = right.m5, b12 = right.m6, b13 = right.m7;
float b20 = right.m8, b21 = right.m9, b22 = right.m10, b23 = right.m11;
float b30 = right.m12, b31 = right.m13, b32 = right.m14, b33 = right.m15;
result.m0 = b00*a00 + b01*a10 + b02*a20 + b03*a30;
result.m1 = b00*a01 + b01*a11 + b02*a21 + b03*a31;
result.m2 = b00*a02 + b01*a12 + b02*a22 + b03*a32;
@ -712,19 +712,19 @@ Matrix MatrixMultiply(Matrix left, Matrix right)
result.m13 = b30*a01 + b31*a11 + b32*a21 + b33*a31;
result.m14 = b30*a02 + b31*a12 + b32*a22 + b33*a32;
result.m15 = b30*a03 + b31*a13 + b32*a23 + b33*a33;
return result;
}
// Returns perspective projection matrix
Matrix MatrixFrustum(double left, double right, double bottom, double top, double near, double far)
Matrix MatrixFrustum(double left, double right, double bottom, double top, double near, double far)
{
Matrix result;
float rl = (right - left);
float tb = (top - bottom);
float fn = (far - near);
result.m0 = (near*2) / rl;
result.m1 = 0;
result.m2 = 0;
@ -741,7 +741,7 @@ Matrix MatrixFrustum(double left, double right, double bottom, double top, doubl
result.m13 = 0;
result.m14 = -(far*near*2) / fn;
result.m15 = 0;
return result;
}
@ -755,14 +755,14 @@ Matrix MatrixPerspective(double fovy, double aspect, double near, double far)
}
// Returns orthographic projection matrix
Matrix MatrixOrtho(double left, double right, double bottom, double top, double near, double far)
Matrix MatrixOrtho(double left, double right, double bottom, double top, double near, double far)
{
Matrix result;
float rl = (right - left);
float tb = (top - bottom);
float fn = (far - near);
result.m0 = 2 / rl;
result.m1 = 0;
result.m2 = 0;
@ -779,7 +779,7 @@ Matrix MatrixOrtho(double left, double right, double bottom, double top, double
result.m13 = -(top + bottom) / tb;
result.m14 = -(far + near) / fn;
result.m15 = 1;
return result;
}
@ -787,14 +787,14 @@ Matrix MatrixOrtho(double left, double right, double bottom, double top, double
Matrix MatrixLookAt(Vector3 eye, Vector3 target, Vector3 up)
{
Matrix result;
Vector3 z = VectorSubtract(eye, target);
VectorNormalize(&z);
Vector3 x = VectorCrossProduct(up, z);
VectorNormalize(&x);
Vector3 y = VectorCrossProduct(z, x);
VectorNormalize(&y);
result.m0 = x.x;
result.m1 = x.y;
result.m2 = x.z;
@ -811,7 +811,7 @@ Matrix MatrixLookAt(Vector3 eye, Vector3 target, Vector3 up)
result.m13 = 0;
result.m14 = 0;
result.m15 = 1;
return result;
}
@ -837,16 +837,16 @@ float QuaternionLength(Quaternion quat)
}
// Normalize provided quaternion
void QuaternionNormalize(Quaternion *q)
void QuaternionNormalize(Quaternion *q)
{
float length, ilength;
length = QuaternionLength(*q);
if (length == 0) length = 1;
ilength = 1.0/length;
q->x *= ilength;
q->y *= ilength;
q->z *= ilength;
@ -854,28 +854,28 @@ void QuaternionNormalize(Quaternion *q)
}
// Calculate two quaternion multiplication
Quaternion QuaternionMultiply(Quaternion q1, Quaternion q2)
Quaternion QuaternionMultiply(Quaternion q1, Quaternion q2)
{
Quaternion result;
float qax = q1.x, qay = q1.y, qaz = q1.z, qaw = q1.w;
float qbx = q2.x, qby = q2.y, qbz = q2.z, qbw = q2.w;
result.x = qax*qbw + qaw*qbx + qay*qbz - qaz*qby;
result.y = qay*qbw + qaw*qby + qaz*qbx - qax*qbz;
result.z = qaz*qbw + qaw*qbz + qax*qby - qay*qbx;
result.w = qaw*qbw - qax*qbx - qay*qby - qaz*qbz;
return result;
}
// Calculates spherical linear interpolation between two quaternions
Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float amount)
Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float amount)
{
Quaternion result;
float cosHalfTheta = q1.x*q2.x + q1.y*q2.y + q1.z*q2.z + q1.w*q2.w;
if (abs(cosHalfTheta) >= 1.0) result = q1;
else
{
@ -892,15 +892,15 @@ Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float amount)
else
{
float ratioA = sin((1 - amount)*halfTheta) / sinHalfTheta;
float ratioB = sin(amount*halfTheta) / sinHalfTheta;
float ratioB = sin(amount*halfTheta) / sinHalfTheta;
result.x = (q1.x*ratioA + q2.x*ratioB);
result.y = (q1.y*ratioA + q2.y*ratioB);
result.z = (q1.z*ratioA + q2.z*ratioB);
result.w = (q1.w*ratioA + q2.w*ratioB);
}
}
return result;
}
@ -956,7 +956,7 @@ Quaternion QuaternionFromMatrix(Matrix matrix)
result.z = s * 0.25;
}
}
return result;
}
@ -966,24 +966,24 @@ Quaternion QuaternionFromAxisAngle(Vector3 axis, float angle)
{
Quaternion result = { 0, 0, 0, 1 };
if (VectorLength(axis) != 0.0)
if (VectorLength(axis) != 0.0)
angle *= 0.5;
VectorNormalize(&axis);
result.x = axis.x * (float)sin(angle);
result.y = axis.y * (float)sin(angle);
result.z = axis.z * (float)sin(angle);
result.w = (float)cos(angle);
QuaternionNormalize(&result);
return result;
}
// Calculates the matrix from the given quaternion
Matrix QuaternionToMatrix(Quaternion q)
Matrix QuaternionToMatrix(Quaternion q)
{
Matrix result;
@ -1021,7 +1021,7 @@ Matrix QuaternionToMatrix(Quaternion q)
result.m13 = 0;
result.m14 = 0;
result.m15 = 1;
return result;
}
@ -1035,7 +1035,7 @@ void QuaternionToAxisAngle(Quaternion q, Vector3 *outAxis, float *outAngle)
resAngle = 2.0f * (float)acos(q.w);
float den = (float)sqrt(1.0 - q.w * q.w);
if (den > 0.0001f)
{
resAxis.x = q.x / den;
@ -1044,11 +1044,11 @@ void QuaternionToAxisAngle(Quaternion q, Vector3 *outAxis, float *outAngle)
}
else
{
// This occurs when the angle is zero.
// This occurs when the angle is zero.
// Not a problem: just set an arbitrary normalized axis.
resAxis.x = 1.0;
}
*outAxis = resAxis;
*outAngle = resAngle;
}

View File

@ -1,19 +1,19 @@
/*********************************************************************************************
*
*
* raymath
*
*
* Some useful functions to work with Vector3, Matrix and Quaternions
*
*
* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
*
* 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.
*
* Permission is granted to anyone to use this software for any purpose, including commercial
* Permission is granted to anyone to use this software for any purpose, including commercial
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* in the product documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented

File diff suppressed because it is too large Load Diff

View File

@ -1,22 +1,22 @@
/*********************************************************************************************
*
*
* rlgl - raylib OpenGL abstraction layer
*
*
* raylib now uses OpenGL 1.1 style functions (rlVertex) that are mapped to selected OpenGL version:
* OpenGL 1.1 - Direct map rl* -> gl*
* OpenGL 3.3+ - Vertex data is stored in VAOs, call rlglDraw() to render
* OpenGL ES 2 - Same behaviour as OpenGL 3.3+ (NOT TESTED)
*
*
* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
*
* 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.
*
* Permission is granted to anyone to use this software for any purpose, including commercial
* Permission is granted to anyone to use this software for any purpose, including commercial
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* in the product documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented

View File

@ -3,17 +3,17 @@
* raylib.shapes
*
* Basic functions to draw 2d Shapes and check collisions
*
*
* Copyright (c) 2013 Ramon Santamaria (Ray San - raysan@raysanweb.com)
*
* 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.
*
* Permission is granted to anyone to use this software for any purpose, including commercial
* Permission is granted to anyone to use this software for any purpose, including commercial
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* in the product documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
@ -28,7 +28,7 @@
#include <stdlib.h> // Required for abs() function
#include <math.h> // Math related functions, sin() and cos() used on DrawCircle*
// sqrt() and pow() and abs() used on CheckCollision*
#include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3+ or ES2
// Security check in case no USE_OPENGL_* defined
@ -110,7 +110,7 @@ void DrawCircle(int centerX, int centerY, float radius, Color color)
// NOTE: Gradient goes from center (color1) to border (color2)
void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Color color2)
{
rlBegin(RL_TRIANGLES);
rlBegin(RL_TRIANGLES);
for (int i=0; i < 360; i += 2)
{
rlColor4ub(color1.r, color1.g, color1.b, color1.a);
@ -142,7 +142,7 @@ void DrawCircleLines(int centerX, int centerY, float radius, Color color)
{
rlBegin(RL_LINES);
rlColor4ub(color.r, color.g, color.b, color.a);
// NOTE: Circle outline is drawn pixel by pixel every degree (0 to 360)
for (int i=0; i < 360; i++)
{
@ -165,7 +165,7 @@ void DrawRectangle(int posX, int posY, int width, int height, Color color)
void DrawRectangleRec(Rectangle rec, Color color)
{
DrawRectangle(rec.x, rec.y, rec.width, rec.height, color);
}
}
// Draw a gradient-filled rectangle
// NOTE: Gradient goes from bottom (color1) to top (color2)
@ -175,9 +175,9 @@ void DrawRectangleGradient(int posX, int posY, int width, int height, Color colo
rlColor4ub(color1.r, color1.g, color1.b, color1.a); rlVertex2i(posX, posY);
rlColor4ub(color2.r, color2.g, color2.b, color2.a); rlVertex2i(posX, posY + height);
rlColor4ub(color2.r, color2.g, color2.b, color2.a); rlVertex2i(posX + width, posY + height);
rlColor4ub(color1.r, color1.g, color1.b, color1.a); rlVertex2i(posX, posY);
rlColor4ub(color2.r, color2.g, color2.b, color2.a); rlVertex2i(posX + width, posY + height);
rlColor4ub(color2.r, color2.g, color2.b, color2.a); rlVertex2i(posX + width, posY + height);
rlColor4ub(color1.r, color1.g, color1.b, color1.a); rlVertex2i(posX + width, posY);
rlEnd();
}
@ -188,16 +188,16 @@ void DrawRectangleV(Vector2 position, Vector2 size, Color color)
#ifdef USE_OPENGL_11
rlBegin(RL_TRIANGLES);
rlColor4ub(color.r, color.g, color.b, color.a);
rlVertex2i(position.x, position.y);
rlVertex2i(position.x, position.y + size.y);
rlVertex2i(position.x + size.x, position.y + size.y);
rlVertex2i(position.x, position.y);
rlVertex2i(position.x + size.x, position.y + size.y);
rlVertex2i(position.x + size.x, position.y + size.y);
rlVertex2i(position.x + size.x, position.y);
rlEnd();
#endif
#endif
#if defined(USE_OPENGL_33) || defined(USE_OPENGL_ES2)
// NOTE: This shape uses QUADS to avoid drawing order issues (view rlglDraw)
@ -206,17 +206,17 @@ void DrawRectangleV(Vector2 position, Vector2 size, Color color)
rlBegin(RL_QUADS);
rlColor4ub(color.r, color.g, color.b, color.a);
rlNormal3f(0.0f, 0.0f, 1.0f); // Normal Pointing Towards Viewer
rlTexCoord2f(0.0f, 0.0f);
rlTexCoord2f(0.0f, 0.0f);
rlVertex2f(position.x, position.y);
rlTexCoord2f(0.0f, 1.0f);
rlTexCoord2f(0.0f, 1.0f);
rlVertex2f(position.x, position.y + size.y);
rlTexCoord2f(1.0f, 1.0f);
rlVertex2f(position.x + size.x, position.y + size.y);
rlTexCoord2f(1.0f, 0.0f);
rlTexCoord2f(1.0f, 1.0f);
rlVertex2f(position.x + size.x, position.y + size.y);
rlTexCoord2f(1.0f, 0.0f);
rlVertex2f(position.x + size.x, position.y);
rlEnd();
@ -231,13 +231,13 @@ void DrawRectangleLines(int posX, int posY, int width, int height, Color color)
rlColor4ub(color.r, color.g, color.b, color.a);
rlVertex2i(posX + 1, posY + 1);
rlVertex2i(posX + width, posY + 1);
rlVertex2i(posX + width, posY + 1);
rlVertex2i(posX + width, posY + height);
rlVertex2i(posX + width, posY + height);
rlVertex2i(posX + 1, posY + height);
rlVertex2i(posX + 1, posY + height);
rlVertex2i(posX + 1, posY + 1);
rlEnd();
@ -260,10 +260,10 @@ void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color)
rlColor4ub(color.r, color.g, color.b, color.a);
rlVertex2f(v1.x, v1.y);
rlVertex2f(v2.x, v2.y);
rlVertex2f(v2.x, v2.y);
rlVertex2f(v3.x, v3.y);
rlVertex2f(v3.x, v3.y);
rlVertex2f(v1.x, v1.y);
rlEnd();
@ -277,12 +277,12 @@ void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color col
rlPushMatrix();
rlTranslatef(center.x, center.y, 0.0);
rlRotatef(rotation, 0, 0, 1);
rlBegin(RL_TRIANGLES);
for (int i=0; i < 360; i += 360/sides)
{
rlColor4ub(color.r, color.g, color.b, color.a);
rlVertex2i(0, 0);
rlVertex2f(sin(DEG2RAD*i) * radius, cos(DEG2RAD*i) * radius);
rlVertex2f(sin(DEG2RAD*(i+360/sides)) * radius, cos(DEG2RAD*(i+360/sides)) * radius);
@ -299,7 +299,7 @@ void DrawPolyEx(Vector2 *points, int numPoints, Color color)
{
rlBegin(RL_TRIANGLES);
rlColor4ub(color.r, color.g, color.b, color.a);
for (int i = 0; i < numPoints - 2; i++)
{
rlVertex2f(points[i].x, points[i].y);
@ -311,14 +311,14 @@ void DrawPolyEx(Vector2 *points, int numPoints, Color color)
}
// Draw polygon lines
// NOTE: Array num elements MUST be passed as parameter to function
// NOTE: Array num elements MUST be passed as parameter to function
void DrawPolyExLines(Vector2 *points, int numPoints, Color color)
{
if (numPoints >= 2)
{
rlBegin(RL_LINES);
rlColor4ub(color.r, color.g, color.b, color.a);
for (int i = 0; i < numPoints - 1; i++)
{
rlVertex2f(points[i].x, points[i].y);
@ -336,9 +336,9 @@ void DrawPolyExLines(Vector2 *points, int numPoints, Color color)
bool CheckCollisionPointRec(Vector2 point, Rectangle rec)
{
bool collision = false;
if ((point.x >= rec.x) && (point.x <= (rec.x + rec.width)) && (point.y >= rec.y) && (point.y <= (rec.y + rec.height))) collision = true;
return collision;
}
@ -355,14 +355,14 @@ bool CheckCollisionPointTriangle(Vector2 point, Vector2 p1, Vector2 p2, Vector2
float alpha = ((p2.y - p3.y)*(point.x - p3.x) + (p3.x - p2.x)*(point.y - p3.y)) /
((p2.y - p3.y)*(p1.x - p3.x) + (p3.x - p2.x)*(p1.y - p3.y));
float beta = ((p3.y - p1.y)*(point.x - p3.x) + (p1.x - p3.x)*(point.y - p3.y)) /
((p2.y - p3.y)*(p1.x - p3.x) + (p3.x - p2.x)*(p1.y - p3.y));
float gamma = 1.0f - alpha - beta;
if ((alpha > 0) && (beta > 0) & (gamma > 0)) collision = true;
return collision;
}
@ -370,12 +370,12 @@ bool CheckCollisionPointTriangle(Vector2 point, Vector2 p1, Vector2 p2, Vector2
bool CheckCollisionRecs(Rectangle rec1, Rectangle rec2)
{
bool collision = false;
int dx = abs((rec1.x + rec1.width / 2) - (rec2.x + rec2.width / 2));
int dy = abs((rec1.y + rec1.height / 2) - (rec2.y + rec2.height / 2));
if ((dx <= (rec1.width / 2 + rec2.width / 2)) && ((dy <= (rec1.height / 2 + rec2.height / 2)))) collision = true;
return collision;
}
@ -383,14 +383,14 @@ bool CheckCollisionRecs(Rectangle rec1, Rectangle rec2)
bool CheckCollisionCircles(Vector2 center1, float radius1, Vector2 center2, float radius2)
{
bool collision = false;
float dx = center2.x - center1.x; // X distance between centers
float dy = center2.y - center1.y; // Y distance between centers
float distance = sqrt(dx*dx + dy*dy); // Distance between centers
if (distance <= (radius1 + radius2)) collision = true;
return collision;
}
@ -398,12 +398,12 @@ bool CheckCollisionCircles(Vector2 center1, float radius1, Vector2 center2, floa
bool CheckCollisionCircleRec(Vector2 center, float radius, Rectangle rec)
{
bool collision = false;
float dx = abs((rec.x + rec.width / 2) - center.x);
float dy = abs((rec.y + rec.height / 2) - center.y);
if ((dx <= (rec.width / 2 + radius)) && (dy <= (rec.height / 2 + radius))) collision = true;
return collision;
}
@ -411,16 +411,16 @@ bool CheckCollisionCircleRec(Vector2 center, float radius, Rectangle rec)
Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2)
{
Rectangle retRec = { 0, 0, 0, 0 };
if (CheckCollisionRecs(rec1, rec2))
{
int dxx = abs(rec1.x - rec2.x);
int dyy = abs(rec1.y - rec2.y);
if (rec1.x <= rec2.x)
{
if (rec1.y <= rec2.y)
{
{
retRec.x = rec2.x;
retRec.y = rec2.y;
retRec.width = rec1.width - dxx;
@ -437,7 +437,7 @@ Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2)
else
{
if (rec1.y <= rec2.y)
{
{
retRec.x = rec1.x;
retRec.y = rec2.y;
retRec.width = rec2.width - dxx;
@ -451,10 +451,10 @@ Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2)
retRec.height = rec2.height - dyy;
}
}
if (retRec.width >= rec2.width) retRec.width = rec2.width;
if (retRec.height >= rec2.height) retRec.height = rec2.height;
}
return retRec;
}
}

View File

@ -3,20 +3,20 @@
* raylib.text
*
* Basic functions to load SpriteFonts and draw Text
*
*
* Uses external lib:
* stb_image - Multiple formats image loading (JPEG, PNG, BMP, TGA, PSD, GIF, HDR, PIC)
*
* Copyright (c) 2013 Ramon Santamaria (Ray San - raysan@raysanweb.com)
*
* 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.
*
* Permission is granted to anyone to use this software for any purpose, including commercial
* Permission is granted to anyone to use this software for any purpose, including commercial
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* in the product documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
@ -82,14 +82,14 @@ static SpriteFont LoadRBMF(const char *fileName); // Load a rBMF font file (ra
//----------------------------------------------------------------------------------
// Module Functions Definition
//----------------------------------------------------------------------------------
extern void LoadDefaultFont()
extern void LoadDefaultFont()
{
defaultFont.numChars = 96; // We know our default font has 94 chars
Image image;
image.width = 128; // We know our default font image is 128 pixels width
image.height = 64; // We know our default font image is 64 pixels height
// Default font is directly defined here (data generated from a sprite font image)
// This way, we reconstruct SpriteFont without creating large global variables
// This data is automatically allocated to Stack and automatically deallocated at the end of this function
@ -119,19 +119,19 @@ extern void LoadDefaultFont()
int charsHeight = 10;
int charsDivisor = 1; // Every char is separated from the consecutive by a 1 pixel divisor, horizontally and vertically
int charsWidth[96] = { 3, 1, 4, 6, 5, 7, 6, 2, 3, 3, 5, 5, 2, 4, 1, 7, 5, 2, 5, 5, 5, 5, 5, 5, 5, 5, 1, 1, 3, 4, 3, 6,
7, 6, 6, 6, 6, 6, 6, 6, 6, 3, 5, 6, 5, 7, 6, 6, 6, 6, 6, 6, 7, 6, 7, 7, 6, 6, 6, 2, 7, 2, 3, 5,
7, 6, 6, 6, 6, 6, 6, 6, 6, 3, 5, 6, 5, 7, 6, 6, 6, 6, 6, 6, 7, 6, 7, 7, 6, 6, 6, 2, 7, 2, 3, 5,
2, 5, 5, 5, 5, 5, 4, 5, 5, 1, 2, 5, 2, 5, 5, 5, 5, 5, 5, 5, 4, 5, 5, 5, 5, 5, 5, 3, 1, 3, 4, 4 };
// Re-construct image from defaultFontData and generate OpenGL texture
//----------------------------------------------------------------------
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 imgData with defaultFontData (convert from bit to pixel!)
for (int i = 0; i < image.width * image.height; i += 32)
{
@ -139,15 +139,15 @@ extern void LoadDefaultFont()
{
if (BIT_CHECK(defaultFontData[counter], j)) image.pixels[i+j] = WHITE;
}
counter++;
if (counter > 256) counter = 0; // Security check...
}
defaultFont.texture = CreateTexture(image, false); // Convert loaded image to OpenGL texture
UnloadImage(image);
// Reconstruct charSet using charsWidth[], charsHeight, charsDivisor, numChars
//------------------------------------------------------------------------------
defaultFont.charSet = (Character *)malloc(defaultFont.numChars * sizeof(Character)); // Allocate space for our character data
@ -155,7 +155,7 @@ extern void LoadDefaultFont()
int currentLine = 0;
int currentPosX = charsDivisor;
int testPosX = charsDivisor;
for (int i = 0; i < defaultFont.numChars; i++)
{
defaultFont.charSet[i].value = FONT_FIRST_CHAR + i; // First char is 32
@ -163,21 +163,21 @@ extern void LoadDefaultFont()
defaultFont.charSet[i].y = charsDivisor + currentLine * (charsHeight + charsDivisor);
defaultFont.charSet[i].w = charsWidth[i];
defaultFont.charSet[i].h = charsHeight;
testPosX += (defaultFont.charSet[i].w + charsDivisor);
if (testPosX >= defaultFont.texture.width)
{
currentLine++;
currentPosX = 2 * charsDivisor + charsWidth[i];
testPosX = currentPosX;
defaultFont.charSet[i].x = charsDivisor;
defaultFont.charSet[i].y = charsDivisor + currentLine * (charsHeight + charsDivisor);
}
else currentPosX = testPosX;
}
TraceLog(INFO, "Default font loaded successfully");
}
@ -194,29 +194,29 @@ SpriteFont GetDefaultFont()
}
// Load a SpriteFont image into GPU memory
SpriteFont LoadSpriteFont(const char* fileName)
SpriteFont LoadSpriteFont(const char* fileName)
{
SpriteFont spriteFont;
Image image;
// Check file extension
if (strcmp(GetExtension(fileName),"rbmf") == 0) spriteFont = LoadRBMF(fileName);
else
{
{
// Use stb_image to load image data!
int imgWidth;
int imgHeight;
int imgBpp;
byte *imgData = stbi_load(fileName, &imgWidth, &imgHeight, &imgBpp, 4); // Force loading to 4 components (RGBA)
// Convert array to pixel array for working convenience
Color *imgDataPixel = (Color *)malloc(imgWidth * imgHeight * sizeof(Color));
Color *imgDataPixelPOT = NULL;
int pix = 0;
for (int i = 0; i < (imgWidth * imgHeight * 4); i += 4)
{
imgDataPixel[pix].r = imgData[i];
@ -225,33 +225,33 @@ SpriteFont LoadSpriteFont(const char* fileName)
imgDataPixel[pix].a = imgData[i+3];
pix++;
}
stbi_image_free(imgData);
// At this point we have a pixel array with all the data...
TraceLog(INFO, "[%s] SpriteFont image loaded: %i x %i", fileName, imgWidth, imgHeight);
// Process bitmap Font pixel data to get measures (Character array)
// spriteFont.charSet data is filled inside the function and memory is allocated!
int numChars = ParseImageData(imgDataPixel, imgWidth, imgHeight, &spriteFont.charSet);
TraceLog(INFO, "[%s] SpriteFont data parsed correctly", fileName);
TraceLog(INFO, "[%s] SpriteFont num chars detected: %i", fileName, numChars);
spriteFont.numChars = numChars;
// Convert image font to POT image before conversion to texture
// Just add the required amount of pixels at the right and bottom sides of image...
int potWidth = GetNextPOT(imgWidth);
int potHeight = GetNextPOT(imgHeight);
// Check if POT texture generation is required (if texture is not already POT)
if ((potWidth != imgWidth) || (potHeight != imgHeight))
{
// 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++)
@ -260,20 +260,20 @@ SpriteFont LoadSpriteFont(const char* fileName)
else imgDataPixelPOT[j*potWidth + i] = MAGENTA;
}
}
TraceLog(WARNING, "SpriteFont texture converted to POT: %ix%i", potWidth, potHeight);
}
free(imgDataPixel);
image.pixels = imgDataPixelPOT;
image.width = potWidth;
image.height = potHeight;
spriteFont.texture = CreateTexture(image, false); // Convert loaded image to OpenGL texture
UnloadImage(image);
}
return spriteFont;
}
@ -290,13 +290,13 @@ void UnloadSpriteFont(SpriteFont spriteFont)
void DrawText(const char* text, int posX, int posY, int fontSize, Color color)
{
Vector2 position = { (float)posX, (float)posY };
int defaultFontSize = 10; // Default Font chars height in pixel
if (fontSize < defaultFontSize) fontSize = defaultFontSize;
int spacing = fontSize / defaultFontSize;
DrawTextEx(defaultFont, text, position, fontSize, spacing, color);
}
@ -308,9 +308,9 @@ void DrawTextEx(SpriteFont spriteFont, const char* text, Vector2 position, int f
int length = strlen(text);
int positionX = (int)position.x;
float scaleFactor;
Character c;
if (fontSize <= spriteFont.charSet[0].h) scaleFactor = 1.0f;
else scaleFactor = (float)fontSize / spriteFont.charSet[0].h;
@ -320,22 +320,22 @@ void DrawTextEx(SpriteFont spriteFont, const char* text, Vector2 position, int f
for(int i = 0; i < length; i++)
{
c = spriteFont.charSet[(int)text[i] - FONT_FIRST_CHAR];
rlColor4ub(tint.r, tint.g, tint.b, tint.a);
rlNormal3f(0.0f, 0.0f, 1.0f); // Normal Pointing Towards Viewer
rlTexCoord2f((float)c.x / spriteFont.texture.width, (float)c.y / spriteFont.texture.height);
rlTexCoord2f((float)c.x / spriteFont.texture.width, (float)c.y / spriteFont.texture.height);
rlVertex2f(positionX, position.y);
rlTexCoord2f((float)c.x / spriteFont.texture.width, (float)(c.y + c.h) / spriteFont.texture.height);
rlTexCoord2f((float)c.x / spriteFont.texture.width, (float)(c.y + c.h) / spriteFont.texture.height);
rlVertex2f(positionX, position.y + (c.h) * scaleFactor);
rlTexCoord2f((float)(c.x + c.w) / spriteFont.texture.width, (float)(c.y + c.h) / spriteFont.texture.height);
rlTexCoord2f((float)(c.x + c.w) / spriteFont.texture.width, (float)(c.y + c.h) / spriteFont.texture.height);
rlVertex2f(positionX + (c.w) * scaleFactor, position.y + (c.h) * scaleFactor);
rlTexCoord2f((float)(c.x + c.w) / spriteFont.texture.width, (float)c.y / spriteFont.texture.height);
rlTexCoord2f((float)(c.x + c.w) / spriteFont.texture.width, (float)c.y / spriteFont.texture.height);
rlVertex2f(positionX + (c.w) * scaleFactor, position.y);
positionX += ((spriteFont.charSet[(int)text[i] - FONT_FIRST_CHAR].w) * scaleFactor + spacing);
}
rlEnd();
@ -347,7 +347,7 @@ void DrawTextEx(SpriteFont spriteFont, const char* text, Vector2 position, int f
const char *FormatText(const char *text, ...)
{
static char buffer[MAX_FORMATTEXT_LENGTH];
va_list args;
va_start(args, text);
vsprintf(buffer, text, args);
@ -372,19 +372,19 @@ Vector2 MeasureTextEx(SpriteFont spriteFont, const char *text, int fontSize, int
int len = strlen(text);
int textWidth = 0;
float scaleFactor;
for (int i = 0; i < len; i++)
{
textWidth += spriteFont.charSet[(int)text[i] - FONT_FIRST_CHAR].w;
}
if (fontSize <= spriteFont.charSet[0].h) scaleFactor = 1.0f;
else scaleFactor = (float)fontSize / spriteFont.charSet[0].h;
Vector2 vec;
vec.x = (float)textWidth * scaleFactor + (len - 1) * spacing; // Adds chars spacing to measure
vec.y = (float)spriteFont.charSet[0].h * scaleFactor;
return vec;
}
@ -402,11 +402,11 @@ void DrawFPS(int posX, int posY)
static float fps;
static int counter = 0;
static int refreshRate = 0;
char buffer[20];
if (counter < refreshRate)
{
{
counter++;
}
else
@ -415,7 +415,7 @@ void DrawFPS(int posX, int posY)
refreshRate = fps;
counter = 0;
}
sprintf(buffer, "%2.0f FPS", fps);
DrawText(buffer, posX, posY, 20, LIME);
}
@ -435,36 +435,36 @@ static int ParseImageData(Color *imgDataPixel, int imgWidth, int imgHeight, Char
{
int charSpacing = 0;
int lineSpacing = 0;
int x = 0;
int y = 0;
Character tempCharSet[MAX_FONTCHARS]; // We allocate a temporal array for charData, once we get the actual charNumber we copy data to a sized array.
for(y = 0; y < imgHeight; y++)
{
{
for(x = 0; x < imgWidth; x++)
{
{
if (!PixelIsMagenta(imgDataPixel[y*imgWidth + x])) break;
}
if (!PixelIsMagenta(imgDataPixel[y*imgWidth + x])) break;
}
charSpacing = x;
lineSpacing = y;
int charHeight = 0;
int j = 0;
while(!PixelIsMagenta(imgDataPixel[(lineSpacing + j)*imgWidth + charSpacing])) j++;
charHeight = j;
// Check array values to get characters: value, x, y, w, h
int index = 0;
int lineToRead = 0;
int xPosToRead = charSpacing;
while((lineSpacing + lineToRead * (charHeight + lineSpacing)) < imgHeight)
{
while((xPosToRead < imgWidth) &&
@ -474,22 +474,22 @@ static int ParseImageData(Color *imgDataPixel, int imgWidth, int imgHeight, Char
tempCharSet[index].x = xPosToRead;
tempCharSet[index].y = lineSpacing + lineToRead * (charHeight + lineSpacing);
tempCharSet[index].h = charHeight;
int charWidth = 0;
while(!PixelIsMagenta(imgDataPixel[(lineSpacing + (charHeight+lineSpacing)*lineToRead)*imgWidth + xPosToRead + charWidth])) charWidth++;
tempCharSet[index].w = charWidth;
index++;
xPosToRead += (charWidth + charSpacing);
}
lineToRead++;
xPosToRead = charSpacing;
}
// We got tempCharSet populated with char data and the number of chars (index)
// Now we move temp data to real charSet (passed as parameter to the function)
(*charSet) = (Character *)malloc(index * sizeof(Character)); // BE CAREFUL! This memory should be freed!
@ -531,7 +531,7 @@ static SpriteFont LoadRBMF(const char *fileName)
short imgHeight; // Image height - always POT (power-of-two)
short numChars; // Number of characters contained
short charHeight; // Characters height - the same for all characters
char compType; // Compression type:
char compType; // Compression type:
// 4 MSB --> image data compression
// 4 LSB --> chars data compression
char charsDataType; // Char data type provided
@ -539,42 +539,42 @@ static SpriteFont LoadRBMF(const char *fileName)
SpriteFont spriteFont;
Image image;
rbmfInfoHeader rbmfHeader;
unsigned int *rbmfFileData;
unsigned char *rbmfCharWidthData;
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
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)
{
@ -582,24 +582,24 @@ static SpriteFont LoadRBMF(const char *fileName)
{
if (BIT_CHECK(rbmfFileData[counter], j)) image.pixels[i+j] = WHITE;
}
counter++;
}
TraceLog(INFO, "[%s] Image reconstructed correctly, now converting it to texture", fileName);
spriteFont.texture = CreateTexture(image, false);
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
int currentLine = 0;
int currentPosX = charsDivisor;
int testPosX = charsDivisor;
for (int i = 0; i < spriteFont.numChars; i++)
{
spriteFont.charSet[i].value = (int)rbmfHeader.firstChar + i;
@ -607,27 +607,27 @@ static SpriteFont LoadRBMF(const char *fileName)
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++;
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;
}
TraceLog(INFO, "[%s] rBMF file loaded correctly as SpriteFont", fileName);
fclose(rbmfFile);
free(rbmfFileData); // Now we can free loaded data from RAM memory
free(rbmfCharWidthData);
free(rbmfCharWidthData);
return spriteFont;
}
@ -636,8 +636,8 @@ static SpriteFont LoadRBMF(const char *fileName)
static SpriteFont GenerateFromTTF(const char *fileName, int fontSize)
{
SpriteFont font;
// TODO: Load TTF and generate bitmap font and chars data
return font;
}

View File

@ -3,20 +3,20 @@
* raylib.textures
*
* Basic functions to load and draw Textures (2d)
*
*
* Uses external lib:
* stb_image - Multiple formats image loading (JPEG, PNG, BMP, TGA, PSD, GIF, PIC)
*
* Copyright (c) 2013 Ramon Santamaria (Ray San - raysan@raysanweb.com)
*
* 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.
*
* Permission is granted to anyone to use this software for any purpose, including commercial
* Permission is granted to anyone to use this software for any purpose, including commercial
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* in the product documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
@ -83,12 +83,12 @@ static ImageEx LoadDDS(const char *fileName);
Image LoadImage(const char *fileName)
{
Image image;
// Initial values
image.pixels = NULL;
image.width = 0;
image.height = 0;
if ((strcmp(GetExtension(fileName),"png") == 0) ||
(strcmp(GetExtension(fileName),"bmp") == 0) ||
(strcmp(GetExtension(fileName),"tga") == 0) ||
@ -96,22 +96,22 @@ Image LoadImage(const char *fileName)
(strcmp(GetExtension(fileName),"gif") == 0) ||
(strcmp(GetExtension(fileName),"psd") == 0) ||
(strcmp(GetExtension(fileName),"pic") == 0))
{
{
int imgWidth;
int imgHeight;
int imgBpp;
// NOTE: Using stb_image to load images (Supports: BMP, TGA, PNG, JPG, ...)
// Force loading to 4 components (RGBA)
byte *imgData = stbi_load(fileName, &imgWidth, &imgHeight, &imgBpp, 4);
byte *imgData = stbi_load(fileName, &imgWidth, &imgHeight, &imgBpp, 4);
if (imgData != NULL)
{
// Convert array to pixel array for working convenience
image.pixels = (Color *)malloc(imgWidth * imgHeight * sizeof(Color));
int pix = 0;
for (int i = 0; i < (imgWidth * imgHeight * 4); i += 4)
{
image.pixels[pix].r = imgData[i];
@ -120,12 +120,12 @@ Image LoadImage(const char *fileName)
image.pixels[pix].a = imgData[i+3];
pix++;
}
stbi_image_free(imgData);
image.width = imgWidth;
image.height = imgHeight;
TraceLog(INFO, "[%s] Image loaded successfully", fileName);
}
else TraceLog(WARNING, "[%s] Image could not be loaded", fileName);
@ -133,17 +133,17 @@ Image LoadImage(const char *fileName)
else if (strcmp(GetExtension(fileName),"dds") == 0)
{
// NOTE: DDS uncompressed images can also be loaded (discarding mipmaps...)
ImageEx imageDDS = LoadDDS(fileName);
if (imageDDS.compFormat == 0)
{
image.pixels = (Color *)malloc(imageDDS.width * imageDDS.height * sizeof(Color));
image.width = imageDDS.width;
image.height = imageDDS.height;
int pix = 0;
for (int i = 0; i < (image.width * image.height * 4); i += 4)
{
image.pixels[pix].r = imageDDS.data[i];
@ -152,16 +152,16 @@ Image LoadImage(const char *fileName)
image.pixels[pix].a = imageDDS.data[i+3];
pix++;
}
free(imageDDS.data);
TraceLog(INFO, "[%s] Image loaded successfully", fileName);
}
else TraceLog(WARNING, "[%s] Compressed image data could not be loaded", fileName);
else TraceLog(WARNING, "[%s] Compressed image data could not be loaded", fileName);
}
else TraceLog(WARNING, "[%s] Image extension not recognized, it can't be loaded", fileName);
// ALTERNATIVE: We can load pixel data directly into Color struct pixels array,
// ALTERNATIVE: We can load pixel data directly into Color struct pixels array,
// to do that struct data alignment should be the right one (4 byte); it is.
//image.pixels = stbi_load(fileName, &imgWidth, &imgHeight, &imgBpp, 4);
@ -172,7 +172,7 @@ Image LoadImage(const char *fileName)
Image LoadImageFromRES(const char *rresName, int resId)
{
// TODO: rresName could be directly a char array with all the data! --> support it! :P
Image image;
bool found = false;
@ -180,9 +180,9 @@ Image LoadImageFromRES(const char *rresName, int resId)
unsigned char version; // rRES file version and subversion
char useless; // rRES header reserved data
short numRes;
ResInfoHeader infoHeader;
FILE *rresFile = fopen(rresName, "rb");
if (!rresFile) TraceLog(WARNING, "[%s] Could not open raylib resource file", rresName);
@ -195,7 +195,7 @@ Image LoadImageFromRES(const char *rresName, int resId)
fread(&id[3], sizeof(char), 1, rresFile);
fread(&version, sizeof(char), 1, rresFile);
fread(&useless, sizeof(char), 1, rresFile);
if ((id[0] != 'r') && (id[1] != 'R') && (id[2] != 'E') &&(id[3] != 'S'))
{
TraceLog(WARNING, "[%s] This is not a valid raylib resource file", rresName);
@ -204,15 +204,15 @@ Image LoadImageFromRES(const char *rresName, int resId)
{
// Read number of resources embedded
fread(&numRes, sizeof(short), 1, rresFile);
for (int i = 0; i < numRes; i++)
{
fread(&infoHeader, sizeof(ResInfoHeader), 1, rresFile);
if (infoHeader.id == resId)
{
found = true;
// Check data is of valid IMAGE type
if (infoHeader.type == 0) // IMAGE data type
{
@ -221,25 +221,25 @@ Image LoadImageFromRES(const char *rresName, int resId)
short imgWidth, imgHeight;
char colorFormat, mipmaps;
fread(&imgWidth, sizeof(short), 1, rresFile); // Image width
fread(&imgHeight, sizeof(short), 1, rresFile); // Image height
fread(&colorFormat, 1, 1, rresFile); // Image data color format (default: RGBA 32 bit)
fread(&mipmaps, 1, 1, rresFile); // Mipmap images included (default: 0)
image.width = (int)imgWidth;
image.height = (int)imgHeight;
unsigned char *data = malloc(infoHeader.size);
fread(data, infoHeader.size, 1, rresFile);
unsigned char *imgData = DecompressData(data, infoHeader.size, infoHeader.srcSize);
image.pixels = (Color *)malloc(sizeof(Color)*imgWidth*imgHeight);
int pix = 0;
for (int i = 0; i < (imgWidth*imgHeight*4); i += 4)
{
image.pixels[pix].r = imgData[i];
@ -248,11 +248,11 @@ Image LoadImageFromRES(const char *rresName, int resId)
image.pixels[pix].a = imgData[i+3];
pix++;
}
free(imgData);
free(data);
TraceLog(INFO, "[%s] Image loaded successfully from resource, size: %ix%i", rresName, image.width, image.height);
}
else
@ -272,18 +272,18 @@ Image LoadImageFromRES(const char *rresName, int resId)
case 4: break; // RAW: No parameters
default: break;
}
// Jump DATA to read next infoHeader
fseek(rresFile, infoHeader.size, SEEK_CUR);
}
}
}
fclose(rresFile);
}
if (!found) TraceLog(WARNING, "[%s] Required resource id [%i] could not be found in the raylib resource file", rresName, resId);
return image;
}
@ -295,7 +295,7 @@ Texture2D LoadTexture(const char *fileName)
if (strcmp(GetExtension(fileName),"dds") == 0)
{
ImageEx image = LoadDDS(fileName);
if (image.compFormat == 0)
{
texture.id = rlglLoadTexture(image.data, image.width, image.height, false);
@ -306,26 +306,26 @@ Texture2D LoadTexture(const char *fileName)
texture.id = rlglLoadCompressedTexture(image.data, image.width, image.height, image.mipmaps, image.compFormat);
#endif
}
texture.width = image.width;
texture.height = image.height;
if (texture.id == 0) TraceLog(WARNING, "[%s] DDS texture could not be loaded", fileName);
else TraceLog(INFO, "[%s] DDS texture loaded successfully", fileName);
free(image.data);
}
else
{
Image image = LoadImage(fileName);
if (image.pixels != NULL)
{
texture = CreateTexture(image, false);
UnloadImage(image);
}
}
return texture;
}
@ -337,7 +337,7 @@ Texture2D LoadTextureFromRES(const char *rresName, int resId)
Image image = LoadImageFromRES(rresName, resId);
texture = CreateTexture(image, false);
UnloadImage(image);
return texture;
}
@ -371,7 +371,7 @@ void DrawTextureEx(Texture2D texture, Vector2 position, float rotation, float sc
Rectangle sourceRec = { 0, 0, texture.width, texture.height };
Rectangle destRec = { (int)position.x, (int)position.y, texture.width*scale, texture.height*scale };
Vector2 origin = { 0, 0 };
DrawTexturePro(texture, sourceRec, destRec, origin, rotation, tint);
}
@ -380,7 +380,7 @@ void DrawTextureRec(Texture2D texture, Rectangle sourceRec, Vector2 position, Co
{
Rectangle destRec = { (int)position.x, (int)position.y, sourceRec.width, sourceRec.height };
Vector2 origin = { 0, 0 };
DrawTexturePro(texture, sourceRec, destRec, origin, 0, tint);
}
@ -389,34 +389,34 @@ void DrawTextureRec(Texture2D texture, Rectangle sourceRec, Vector2 position, Co
void DrawTexturePro(Texture2D texture, Rectangle sourceRec, Rectangle destRec, Vector2 origin, float rotation, Color tint)
{
rlEnableTexture(texture.id);
rlPushMatrix();
rlTranslatef(destRec.x, destRec.y, 0);
rlRotatef(rotation, 0, 0, 1);
rlTranslatef(-origin.x, -origin.y, 0);
rlBegin(RL_QUADS);
rlColor4ub(tint.r, tint.g, tint.b, tint.a);
rlNormal3f(0.0f, 0.0f, 1.0f); // Normal vector pointing towards viewer
// Bottom-left corner for texture and quad
rlTexCoord2f((float)sourceRec.x / texture.width, (float)sourceRec.y / texture.height);
rlTexCoord2f((float)sourceRec.x / texture.width, (float)sourceRec.y / texture.height);
rlVertex2f(0.0f, 0.0f);
// Bottom-right corner for texture and quad
rlTexCoord2f((float)sourceRec.x / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height);
rlVertex2f(0.0f, destRec.height);
// Top-right corner for texture and quad
rlTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height);
rlTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height);
rlVertex2f(destRec.width, destRec.height);
// Top-left corner for texture and quad
rlTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)sourceRec.y / texture.height);
rlVertex2f(destRec.width, 0.0f);
rlEnd();
rlPopMatrix();
rlDisableTexture();
}
@ -425,25 +425,25 @@ void DrawTexturePro(Texture2D texture, Rectangle sourceRec, Rectangle destRec, V
Texture2D CreateTexture(Image image, bool genMipmaps)
{
Texture2D texture;
// Init texture to default values
texture.id = 0;
texture.width = 0;
texture.height = 0;
if (image.pixels != NULL)
{
unsigned char *imgData = malloc(image.width * image.height * 4);
int j = 0;
for (int i = 0; i < image.width * image.height * 4; i += 4)
{
imgData[i] = image.pixels[j].r;
imgData[i+1] = image.pixels[j].g;
imgData[i+2] = image.pixels[j].b;
imgData[i+3] = image.pixels[j].a;
j++;
}
@ -452,24 +452,24 @@ Texture2D CreateTexture(Image image, bool genMipmaps)
texture.width = image.width;
texture.height = image.height;
TraceLog(INFO, "[ID %i] Texture created successfully", texture.id);
free(imgData);
}
else TraceLog(WARNING, "Texture could not be created, image data is not valid");
return texture;
}
// Loading DDS image data (compressed or uncompressed)
// NOTE: Compressed data loading not supported on OpenGL 1.1
ImageEx LoadDDS(const char *fileName)
{
{
#define FOURCC_DXT1 0x31545844 // Equivalent to "DXT1" in ASCII
#define FOURCC_DXT3 0x33545844 // Equivalent to "DXT3" in ASCII
#define FOURCC_DXT5 0x35545844 // Equivalent to "DXT5" in ASCII
#ifndef GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
#endif
@ -481,7 +481,7 @@ ImageEx LoadDDS(const char *fileName)
#ifndef GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
#endif
// DDS Pixel Format
typedef struct {
unsigned int size;
@ -493,7 +493,7 @@ ImageEx LoadDDS(const char *fileName)
unsigned int bitMask;
unsigned int aBitMask;
} ddsPixelFormat;
// DDS Header (124 bytes)
typedef struct {
unsigned int size;
@ -511,12 +511,12 @@ ImageEx LoadDDS(const char *fileName)
unsigned int caps4;
unsigned int reserved2;
} ddsHeader;
ImageEx image;
ddsHeader header;
FILE *ddsFile = fopen(fileName, "rb");
if (ddsFile == NULL)
{
TraceLog(WARNING, "DDS File could not be opened");
@ -525,16 +525,16 @@ ImageEx LoadDDS(const char *fileName)
{
// Verify the type of file
char filecode[4];
fread(filecode, 1, 4, ddsFile);
if (strncmp(filecode, "DDS ", 4) != 0)
{
if (strncmp(filecode, "DDS ", 4) != 0)
{
TraceLog(WARNING, "DDS File does not seem to be valid");
fclose(ddsFile);
}
else
{
{
// Get the surface descriptor
fread(&header, sizeof(ddsHeader), 1, ddsFile);
@ -542,25 +542,25 @@ ImageEx LoadDDS(const char *fileName)
TraceLog(DEBUG, "[%s] DDS file pixel format size: %i", fileName, header.ddspf.size);
TraceLog(DEBUG, "[%s] DDS file pixel format flags: 0x%x", fileName, header.ddspf.flags);
TraceLog(DEBUG, "[%s] DDS file format: 0x%x", fileName, header.ddspf.fourCC);
image.width = header.width;
image.height = header.height;
image.mipmaps = 1;
image.compFormat = 0;
if (header.ddspf.flags == 0x40 && header.ddspf.rgbBitCount == 24) // DDS_RGB, no compressed
{
image.data = (unsigned char *)malloc(header.width * header.height * 4);
unsigned char *buffer = (unsigned char *)malloc(header.width * header.height * 3);
fread(buffer, image.width*image.height*3, 1, ddsFile);
unsigned char *src = buffer;
unsigned char *dest = image.data;
for(int y = 0; y < image.height; y++)
for(int y = 0; y < image.height; y++)
{
for(int x = 0; x < image.width; x++)
for(int x = 0; x < image.width; x++)
{
*dest++ = *src++;
*dest++ = *src++;
@ -568,49 +568,49 @@ ImageEx LoadDDS(const char *fileName)
*dest++ = 255;
}
}
free(buffer);
}
else if (header.ddspf.flags == 0x41 && header.ddspf.rgbBitCount == 32) // DDS_RGBA, no compressed
{
image.data = (unsigned char *)malloc(header.width * header.height * 4);
fread(image.data, image.width*image.height*4, 1, ddsFile);
image.mipmaps = 1;
image.compFormat = 0;
}
else if ((header.ddspf.flags == 0x04) && (header.ddspf.fourCC > 0))
{
#ifdef USE_OPENGL_11
#ifdef USE_OPENGL_11
TraceLog(WARNING, "[%s] DDS image uses compression, not supported by current OpenGL version", fileName);
TraceLog(WARNING, "[%s] DDS compressed files require OpenGL 3.2+ or ES 2.0", fileName);
fclose(ddsFile);
#else
int bufsize;
// Calculate data size, including all mipmaps
if (header.mipMapCount > 1) bufsize = header.pitchOrLinearSize * 2;
else bufsize = header.pitchOrLinearSize;
image.data = (unsigned char*)malloc(bufsize * sizeof(unsigned char));
fread(image.data, 1, bufsize, ddsFile);
else bufsize = header.pitchOrLinearSize;
image.data = (unsigned char*)malloc(bufsize * sizeof(unsigned char));
fread(image.data, 1, bufsize, ddsFile);
// Close file pointer
fclose(ddsFile);
image.mipmaps = header.mipMapCount;
image.compFormat = 0;
switch(header.ddspf.fourCC)
{
case FOURCC_DXT1: image.compFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; break;
case FOURCC_DXT3: image.compFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; break;
case FOURCC_DXT5: image.compFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; break;
{
case FOURCC_DXT1: image.compFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; break;
case FOURCC_DXT3: image.compFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; break;
case FOURCC_DXT5: image.compFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; break;
default: break;
}
// NOTE: Image num color components not required... for now...
//if (fourCC == FOURCC_DXT1) image.components = 3;
//else image.components = 4;
@ -618,6 +618,6 @@ ImageEx LoadDDS(const char *fileName)
}
}
}
return image;
}

View File

@ -3,21 +3,21 @@
* raylib.utils
*
* Utils Functions Definitions
*
* Uses external libs:
*
* Uses external libs:
* tinfl - zlib DEFLATE algorithm decompression lib
* stb_image_write - PNG writting functions
*
*
* Copyright (c) 2013 Ramon Santamaria (Ray San - raysan@raysanweb.com)
*
* 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.
*
* Permission is granted to anyone to use this software for any purpose, including commercial
* Permission is granted to anyone to use this software for any purpose, including commercial
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* in the product documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
@ -54,10 +54,10 @@ unsigned char *DecompressData(const unsigned char *data, unsigned long compSize,
{
int tempUncompSize;
unsigned char *pUncomp;
// Allocate buffer to hold decompressed data
pUncomp = (mz_uint8 *)malloc((size_t)uncompSize);
// Check correct memory allocation
if (!pUncomp)
{
@ -67,13 +67,13 @@ unsigned char *DecompressData(const unsigned char *data, unsigned long compSize,
{
// Decompress data
tempUncompSize = tinfl_decompress_mem_to_mem(pUncomp, (size_t)uncompSize, data, compSize, 1);
if (tempUncompSize == -1)
{
TraceLog(WARNING, "Data decompression failed");
free(pUncomp);
}
if (uncompSize != (int)tempUncompSize)
{
TraceLog(WARNING, "Expected uncompressed size do not match, data may be corrupted");
@ -83,7 +83,7 @@ unsigned char *DecompressData(const unsigned char *data, unsigned long compSize,
TraceLog(INFO, "Data decompressed successfully from %u bytes to %u bytes", (mz_uint32)compSize, (mz_uint32)tempUncompSize);
}
return pUncomp;
}
@ -92,7 +92,7 @@ unsigned char *DecompressData(const unsigned char *data, unsigned long compSize,
void WriteBitmap(const char *fileName, unsigned char *imgData, int width, int height)
{
int filesize = 54 + 3*width*height;
unsigned char bmpFileHeader[14] = {'B','M', 0,0,0,0, 0,0, 0,0, 54,0,0,0}; // Standard BMP file header
unsigned char bmpInfoHeader[40] = {40,0,0,0, 0,0,0,0, 0,0,0,0, 1,0, 24,0}; // Standard BMP info header
@ -111,11 +111,11 @@ void WriteBitmap(const char *fileName, unsigned char *imgData, int width, int he
bmpInfoHeader[11] = (unsigned char)(height>>24);
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
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++)
{
@ -143,14 +143,14 @@ void TraceLog(int msgType, const char *text, ...)
{
va_list args;
int traceDebugMsgs = 1;
#ifdef DO_NOT_TRACE_DEBUG_MSGS
traceDebugMsgs = 0;
#endif
// NOTE: If trace log file not set, output redirected to stdout
// NOTE: If trace log file not set, output redirected to stdout
if (logstream == NULL) logstream = stdout;
switch(msgType)
{
case INFO: fprintf(logstream, "INFO: "); break;
@ -159,16 +159,16 @@ void TraceLog(int msgType, const char *text, ...)
case DEBUG: if (traceDebugMsgs) fprintf(logstream, "DEBUG: "); break;
default: break;
}
if ((msgType != DEBUG) || ((msgType == DEBUG) && (traceDebugMsgs)))
{
va_start(args, text);
vfprintf(logstream, text, args);
va_end(args);
fprintf(logstream, "\n");
}
if (msgType == ERROR) exit(1); // If ERROR message, exit program
}
@ -196,7 +196,7 @@ void RecordMalloc(int mallocType, int mallocSize, const char *msg)
}
// Get the extension for a filename
const char *GetExtension(const char *fileName)
const char *GetExtension(const char *fileName)
{
const char *dot = strrchr(fileName, '.');
if(!dot || dot == fileName) return "";

View File

@ -3,17 +3,17 @@
* raylib.utils
*
* Some utility functions: rRES files data decompression
*
*
* Copyright (c) 2013 Ramon Santamaria (Ray San - raysan@raysanweb.com)
*
* 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.
*
* Permission is granted to anyone to use this software for any purpose, including commercial
* Permission is granted to anyone to use this software for any purpose, including commercial
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* in the product documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented