From d2b98fbb5ce8d82bb2c46f3d66ffda58d6ad5c6f Mon Sep 17 00:00:00 2001 From: raysan5 Date: Wed, 3 Sep 2014 16:51:28 +0200 Subject: [PATCH] Removed useless spaces --- src/audio.c | 288 +++++++++++------------ src/core.c | 196 +++++++-------- src/models.c | 628 ++++++++++++++++++++++++------------------------- src/raylib.h | 24 +- src/raymath.c | 246 +++++++++---------- src/raymath.h | 16 +- src/rlgl.c | 542 +++++++++++++++++++++--------------------- src/rlgl.h | 16 +- src/shapes.c | 114 ++++----- src/text.c | 228 +++++++++--------- src/textures.c | 220 ++++++++--------- src/utils.c | 46 ++-- src/utils.h | 12 +- 13 files changed, 1288 insertions(+), 1288 deletions(-) diff --git a/src/audio.c b/src/audio.c index 2866de49..e1d9b4a1 100644 --- a/src/audio.c +++ b/src/audio.c @@ -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); // - + 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, ¤tMusic.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, ¤tMusic.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; } diff --git a/src/core.c b/src/core.c index 1fdf5441..04c96f4a 100644 --- a/src/core.c +++ b/src/core.c @@ -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(); //---------------------------------------------------------------------------------- } diff --git a/src/models.c b/src/models.c index d66d2cce..95dbae7c 100644 --- a/src/models.c +++ b/src/models.c @@ -5,15 +5,15 @@ * Basic functions to draw 3d shapes and load/draw 3d models (.OBJ) * * 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 @@ -72,60 +72,60 @@ void DrawCube(Vector3 position, float width, float height, float lenght, Color c //rlTranslatef(0.0f, 0.0f, 0.0f); //rlScalef(2.0f, 2.0f, 2.0f); //rlRotatef(45, 0, 1, 0); - + rlBegin(RL_TRIANGLES); - rlColor4ub(color.r, color.g, color.b, color.a); - + rlColor4ub(color.r, color.g, color.b, color.a); + // Front Face ----------------------------------------------------- rlVertex3f(x-width/2, y-height/2, z+lenght/2); // Bottom Left rlVertex3f(x+width/2, y-height/2, z+lenght/2); // Bottom Right rlVertex3f(x-width/2, y+height/2, z+lenght/2); // Top Left - + rlVertex3f(x+width/2, y+height/2, z+lenght/2); // Top Right rlVertex3f(x-width/2, y+height/2, z+lenght/2); // Top Left rlVertex3f(x+width/2, y-height/2, z+lenght/2); // Bottom Right - + // Back Face ------------------------------------------------------ rlVertex3f(x-width/2, y-height/2, z-lenght/2); // Bottom Left rlVertex3f(x-width/2, y+height/2, z-lenght/2); // Top Left rlVertex3f(x+width/2, y-height/2, z-lenght/2); // Bottom Right - + rlVertex3f(x+width/2, y+height/2, z-lenght/2); // Top Right rlVertex3f(x+width/2, y-height/2, z-lenght/2); // Bottom Right rlVertex3f(x-width/2, y+height/2, z-lenght/2); // Top Left - + // Top Face ------------------------------------------------------- rlVertex3f(x-width/2, y+height/2, z-lenght/2); // Top Left rlVertex3f(x-width/2, y+height/2, z+lenght/2); // Bottom Left rlVertex3f(x+width/2, y+height/2, z+lenght/2); // Bottom Right - + rlVertex3f(x+width/2, y+height/2, z-lenght/2); // Top Right rlVertex3f(x-width/2, y+height/2, z-lenght/2); // Top Left rlVertex3f(x+width/2, y+height/2, z+lenght/2); // Bottom Right - + // Bottom Face ---------------------------------------------------- rlVertex3f(x-width/2, y-height/2, z-lenght/2); // Top Left rlVertex3f(x+width/2, y-height/2, z+lenght/2); // Bottom Right rlVertex3f(x-width/2, y-height/2, z+lenght/2); // Bottom Left - + rlVertex3f(x+width/2, y-height/2, z-lenght/2); // Top Right rlVertex3f(x+width/2, y-height/2, z+lenght/2); // Bottom Right rlVertex3f(x-width/2, y-height/2, z-lenght/2); // Top Left - + // Right face ----------------------------------------------------- rlVertex3f(x+width/2, y-height/2, z-lenght/2); // Bottom Right rlVertex3f(x+width/2, y+height/2, z-lenght/2); // Top Right rlVertex3f(x+width/2, y+height/2, z+lenght/2); // Top Left - + rlVertex3f(x+width/2, y-height/2, z+lenght/2); // Bottom Left rlVertex3f(x+width/2, y-height/2, z-lenght/2); // Bottom Right rlVertex3f(x+width/2, y+height/2, z+lenght/2); // Top Left - + // Left Face ------------------------------------------------------ rlVertex3f(x-width/2, y-height/2, z-lenght/2); // Bottom Right rlVertex3f(x-width/2, y+height/2, z+lenght/2); // Top Left rlVertex3f(x-width/2, y+height/2, z-lenght/2); // Top Right - + rlVertex3f(x-width/2, y-height/2, z+lenght/2); // Bottom Left rlVertex3f(x-width/2, y+height/2, z+lenght/2); // Top Left rlVertex3f(x-width/2, y-height/2, z-lenght/2); // Bottom Right @@ -145,53 +145,53 @@ void DrawCubeWires(Vector3 position, float width, float height, float lenght, Co float x = position.x; float y = position.y; float z = position.z; - + rlPushMatrix(); //rlRotatef(45, 0, 1, 0); - + rlBegin(RL_LINES); - rlColor4ub(color.r, color.g, color.b, color.a); - + rlColor4ub(color.r, color.g, color.b, color.a); + // Front Face ----------------------------------------------------- // Bottom Line rlVertex3f(x-width/2, y-height/2, z+lenght/2); // Bottom Left rlVertex3f(x+width/2, y-height/2, z+lenght/2); // Bottom Right - + // Left Line rlVertex3f(x+width/2, y-height/2, z+lenght/2); // Bottom Right rlVertex3f(x+width/2, y+height/2, z+lenght/2); // Top Right - + // Top Line rlVertex3f(x+width/2, y+height/2, z+lenght/2); // Top Right rlVertex3f(x-width/2, y+height/2, z+lenght/2); // Top Left - + // Right Line rlVertex3f(x-width/2, y+height/2, z+lenght/2); // Top Left rlVertex3f(x-width/2, y-height/2, z+lenght/2); // Bottom Left - + // Back Face ------------------------------------------------------ // Bottom Line rlVertex3f(x-width/2, y-height/2, z-lenght/2); // Bottom Left rlVertex3f(x+width/2, y-height/2, z-lenght/2); // Bottom Right - + // Left Line rlVertex3f(x+width/2, y-height/2, z-lenght/2); // Bottom Right rlVertex3f(x+width/2, y+height/2, z-lenght/2); // Top Right - + // Top Line rlVertex3f(x+width/2, y+height/2, z-lenght/2); // Top Right rlVertex3f(x-width/2, y+height/2, z-lenght/2); // Top Left - + // Right Line rlVertex3f(x-width/2, y+height/2, z-lenght/2); // Top Left rlVertex3f(x-width/2, y-height/2, z-lenght/2); // Bottom Left - + // Top Face ------------------------------------------------------- // Left Line rlVertex3f(x-width/2, y+height/2, z+lenght/2); // Top Left Front rlVertex3f(x-width/2, y+height/2, z-lenght/2); // Top Left Back - + // Right Line rlVertex3f(x+width/2, y+height/2, z+lenght/2); // Top Right Front rlVertex3f(x+width/2, y+height/2, z-lenght/2); // Top Right Back @@ -200,7 +200,7 @@ void DrawCubeWires(Vector3 position, float width, float height, float lenght, Co // Left Line rlVertex3f(x-width/2, y-height/2, z+lenght/2); // Top Left Front rlVertex3f(x-width/2, y-height/2, z-lenght/2); // Top Left Back - + // Right Line rlVertex3f(x+width/2, y-height/2, z+lenght/2); // Top Right Front rlVertex3f(x+width/2, y-height/2, z-lenght/2); // Top Right Back @@ -217,15 +217,15 @@ void DrawCubeTexture(Texture2D texture, Vector3 position, float width, float hei float z = position.z; rlEnableTexture(texture.id); - - //rlPushMatrix(); + + //rlPushMatrix(); // NOTE: Be careful! Function order matters (scale, translate, rotate) //rlScalef(2.0f, 2.0f, 2.0f); //rlTranslatef(2.0f, 0.0f, 0.0f); //rlRotatef(45, 0, 1, 0); - + rlBegin(RL_QUADS); - rlColor4ub(color.r, color.g, color.b, color.a); + rlColor4ub(color.r, color.g, color.b, color.a); // Front Face rlNormal3f(0.0f, 0.0f, 1.0f); // Normal Pointing Towards Viewer rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x-width/2, y-height/2, z+lenght/2); // Bottom Left Of The Texture and Quad @@ -264,7 +264,7 @@ void DrawCubeTexture(Texture2D texture, Vector3 position, float width, float hei rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x-width/2, y+height/2, z-lenght/2); // Top Left Of The Texture and Quad rlEnd(); //rlPopMatrix(); - + rlDisableTexture(); } @@ -281,32 +281,32 @@ void DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color rlTranslatef(centerPos.x, centerPos.y, centerPos.z); rlScalef(radius, radius, radius); //rlRotatef(rotation, 0, 1, 0); - + rlBegin(RL_TRIANGLES); rlColor4ub(color.r, color.g, color.b, color.a); - + for(int i = 0; i < (rings + 2); i++) { for(int j = 0; j < slices; j++) { - rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*i)) * sin(DEG2RAD*(j*360/slices)), - sin(DEG2RAD*(270+(180/(rings + 1))*i)), + rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*i)) * sin(DEG2RAD*(j*360/slices)), + sin(DEG2RAD*(270+(180/(rings + 1))*i)), cos(DEG2RAD*(270+(180/(rings + 1))*i)) * cos(DEG2RAD*(j*360/slices))); - rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i+1))) * sin(DEG2RAD*((j+1)*360/slices)), - sin(DEG2RAD*(270+(180/(rings + 1))*(i+1))), + rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i+1))) * sin(DEG2RAD*((j+1)*360/slices)), + sin(DEG2RAD*(270+(180/(rings + 1))*(i+1))), cos(DEG2RAD*(270+(180/(rings + 1))*(i+1))) * cos(DEG2RAD*((j+1)*360/slices))); - rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i+1))) * sin(DEG2RAD*(j*360/slices)), - sin(DEG2RAD*(270+(180/(rings + 1))*(i+1))), + rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i+1))) * sin(DEG2RAD*(j*360/slices)), + sin(DEG2RAD*(270+(180/(rings + 1))*(i+1))), cos(DEG2RAD*(270+(180/(rings + 1))*(i+1))) * cos(DEG2RAD*(j*360/slices))); - rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*i)) * sin(DEG2RAD*(j*360/slices)), - sin(DEG2RAD*(270+(180/(rings + 1))*i)), + rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*i)) * sin(DEG2RAD*(j*360/slices)), + sin(DEG2RAD*(270+(180/(rings + 1))*i)), cos(DEG2RAD*(270+(180/(rings + 1))*i)) * cos(DEG2RAD*(j*360/slices))); - rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i))) * sin(DEG2RAD*((j+1)*360/slices)), - sin(DEG2RAD*(270+(180/(rings + 1))*(i))), + rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i))) * sin(DEG2RAD*((j+1)*360/slices)), + sin(DEG2RAD*(270+(180/(rings + 1))*(i))), cos(DEG2RAD*(270+(180/(rings + 1))*(i))) * cos(DEG2RAD*((j+1)*360/slices))); - rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i+1))) * sin(DEG2RAD*((j+1)*360/slices)), - sin(DEG2RAD*(270+(180/(rings + 1))*(i+1))), + rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i+1))) * sin(DEG2RAD*((j+1)*360/slices)), + sin(DEG2RAD*(270+(180/(rings + 1))*(i+1))), cos(DEG2RAD*(270+(180/(rings + 1))*(i+1))) * cos(DEG2RAD*((j+1)*360/slices))); } } @@ -321,33 +321,33 @@ void DrawSphereWires(Vector3 centerPos, float radius, int rings, int slices, Col rlTranslatef(centerPos.x, centerPos.y, centerPos.z); rlScalef(radius, radius, radius); //rlRotatef(rotation, 0, 1, 0); - + rlBegin(RL_LINES); rlColor4ub(color.r, color.g, color.b, color.a); - + for(int i = 0; i < (rings + 2); i++) { for(int j = 0; j < slices; j++) { - rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*i)) * sin(DEG2RAD*(j*360/slices)), - sin(DEG2RAD*(270+(180/(rings + 1))*i)), + rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*i)) * sin(DEG2RAD*(j*360/slices)), + sin(DEG2RAD*(270+(180/(rings + 1))*i)), cos(DEG2RAD*(270+(180/(rings + 1))*i)) * cos(DEG2RAD*(j*360/slices))); - rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i+1))) * sin(DEG2RAD*((j+1)*360/slices)), - sin(DEG2RAD*(270+(180/(rings + 1))*(i+1))), + rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i+1))) * sin(DEG2RAD*((j+1)*360/slices)), + sin(DEG2RAD*(270+(180/(rings + 1))*(i+1))), cos(DEG2RAD*(270+(180/(rings + 1))*(i+1))) * cos(DEG2RAD*((j+1)*360/slices))); - - rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i+1))) * sin(DEG2RAD*((j+1)*360/slices)), - sin(DEG2RAD*(270+(180/(rings + 1))*(i+1))), + + rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i+1))) * sin(DEG2RAD*((j+1)*360/slices)), + sin(DEG2RAD*(270+(180/(rings + 1))*(i+1))), cos(DEG2RAD*(270+(180/(rings + 1))*(i+1))) * cos(DEG2RAD*((j+1)*360/slices))); - rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i+1))) * sin(DEG2RAD*(j*360/slices)), - sin(DEG2RAD*(270+(180/(rings + 1))*(i+1))), + rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i+1))) * sin(DEG2RAD*(j*360/slices)), + sin(DEG2RAD*(270+(180/(rings + 1))*(i+1))), cos(DEG2RAD*(270+(180/(rings + 1))*(i+1))) * cos(DEG2RAD*(j*360/slices))); - - rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i+1))) * sin(DEG2RAD*(j*360/slices)), - sin(DEG2RAD*(270+(180/(rings + 1))*(i+1))), + + rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i+1))) * sin(DEG2RAD*(j*360/slices)), + sin(DEG2RAD*(270+(180/(rings + 1))*(i+1))), cos(DEG2RAD*(270+(180/(rings + 1))*(i+1))) * cos(DEG2RAD*(j*360/slices))); - rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*i)) * sin(DEG2RAD*(j*360/slices)), - sin(DEG2RAD*(270+(180/(rings + 1))*i)), + rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*i)) * sin(DEG2RAD*(j*360/slices)), + sin(DEG2RAD*(270+(180/(rings + 1))*i)), cos(DEG2RAD*(270+(180/(rings + 1))*i)) * cos(DEG2RAD*(j*360/slices))); } } @@ -360,7 +360,7 @@ void DrawSphereWires(Vector3 centerPos, float radius, int rings, int slices, Col void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float height, int sides, Color color) { if (sides < 3) sides = 3; - + rlPushMatrix(); rlTranslatef(position.x, position.y, position.z); @@ -375,12 +375,12 @@ void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float h rlVertex3f(sin(DEG2RAD*i) * radiusBottom, 0, cos(DEG2RAD*i) * radiusBottom); //Bottom Left rlVertex3f(sin(DEG2RAD*(i+360/sides)) * radiusBottom, 0, cos(DEG2RAD*(i+360/sides)) * radiusBottom); //Bottom Right rlVertex3f(sin(DEG2RAD*(i+360/sides)) * radiusTop, height, cos(DEG2RAD*(i+360/sides)) * radiusTop); //Top Right - + rlVertex3f(sin(DEG2RAD*i) * radiusTop, height, cos(DEG2RAD*i) * radiusTop); //Top Left rlVertex3f(sin(DEG2RAD*i) * radiusBottom, 0, cos(DEG2RAD*i) * radiusBottom); //Bottom Left rlVertex3f(sin(DEG2RAD*(i+360/sides)) * radiusTop, height, cos(DEG2RAD*(i+360/sides)) * radiusTop); //Top Right } - + // Draw Cap -------------------------------------------------------------------------------------- for(int i = 0; i < 360; i += 360/sides) { @@ -399,7 +399,7 @@ void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float h rlVertex3f(sin(DEG2RAD*(i+360/sides)) * radiusBottom, 0, cos(DEG2RAD*(i+360/sides)) * radiusBottom); } } - + // Draw Base ----------------------------------------------------------------------------------------- for(int i = 0; i < 360; i += 360/sides) { @@ -407,7 +407,7 @@ void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float h rlVertex3f(sin(DEG2RAD*(i+360/sides)) * radiusBottom, 0, cos(DEG2RAD*(i+360/sides)) * radiusBottom); rlVertex3f(sin(DEG2RAD*i) * radiusBottom, 0, cos(DEG2RAD*i) * radiusBottom); } - rlEnd(); + rlEnd(); rlPopMatrix(); } @@ -416,24 +416,24 @@ void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float h void DrawCylinderWires(Vector3 position, float radiusTop, float radiusBottom, float height, int sides, Color color) { if(sides < 3) sides = 3; - + rlPushMatrix(); rlTranslatef(position.x, position.y, position.z); - + rlBegin(RL_LINES); rlColor4ub(color.r, color.g, color.b, color.a); - + for(int i = 0; i < 360; i += 360/sides) { rlVertex3f(sin(DEG2RAD*i) * radiusBottom, 0, cos(DEG2RAD*i) * radiusBottom); rlVertex3f(sin(DEG2RAD*(i+360/sides)) * radiusBottom, 0, cos(DEG2RAD*(i+360/sides)) * radiusBottom); - + rlVertex3f(sin(DEG2RAD*(i+360/sides)) * radiusBottom, 0, cos(DEG2RAD*(i+360/sides)) * radiusBottom); rlVertex3f(sin(DEG2RAD*(i+360/sides)) * radiusTop, height, cos(DEG2RAD*(i+360/sides)) * radiusTop); - + rlVertex3f(sin(DEG2RAD*(i+360/sides)) * radiusTop, height, cos(DEG2RAD*(i+360/sides)) * radiusTop); rlVertex3f(sin(DEG2RAD*i) * radiusTop, height, cos(DEG2RAD*i) * radiusTop); - + rlVertex3f(sin(DEG2RAD*i) * radiusTop, height, cos(DEG2RAD*i) * radiusTop); rlVertex3f(sin(DEG2RAD*i) * radiusBottom, 0, cos(DEG2RAD*i) * radiusBottom); } @@ -449,15 +449,15 @@ void DrawPlane(Vector3 centerPos, Vector2 size, Vector3 rotation, Color color) rlPushMatrix(); rlTranslatef(centerPos.x, centerPos.y, centerPos.z); rlScalef(size.x, 1.0f, size.y); - + // TODO: Review multiples rotations Gimbal-Lock... use matrix or quaternions... rlRotatef(rotation.x, 1, 0, 0); rlRotatef(rotation.y, 0, 1, 0); rlRotatef(rotation.z, 0, 0, 1); - + rlBegin(RL_QUADS); rlColor4ub(color.r, color.g, color.b, color.a); - rlNormal3f(0.0f, 1.0f, 0.0f); + rlNormal3f(0.0f, 1.0f, 0.0f); rlTexCoord2f(0.0f, 0.0f); rlVertex3f(-0.5f, 0.0f, -0.5f); rlTexCoord2f(1.0f, 0.0f); rlVertex3f(0.5f, 0.0f, -0.5f); rlTexCoord2f(1.0f, 1.0f); rlVertex3f(0.5f, 0.0f, 0.5f); @@ -472,7 +472,7 @@ void DrawPlaneEx(Vector3 centerPos, Vector2 size, Vector3 rotation, int slicesX, { float quadWidth = size.x / slicesX; float quadLenght = size.y / slicesZ; - + float texPieceW = 1 / size.x; float texPieceH = 1 / size.y; @@ -480,16 +480,16 @@ void DrawPlaneEx(Vector3 centerPos, Vector2 size, Vector3 rotation, int slicesX, rlPushMatrix(); rlTranslatef(-size.x / 2, 0.0f, -size.y / 2); rlTranslatef(centerPos.x, centerPos.y, centerPos.z); - + // TODO: Review multiples rotations Gimbal-Lock... use matrix or quaternions... rlRotatef(rotation.x, 1, 0, 0); rlRotatef(rotation.y, 0, 1, 0); rlRotatef(rotation.z, 0, 0, 1); - + rlBegin(RL_QUADS); rlColor4ub(color.r, color.g, color.b, color.a); rlNormal3f(0.0f, 1.0f, 0.0f); - + for (int z = 0; z < slicesZ; z++) { for (int x = 0; x < slicesX; x++) @@ -497,13 +497,13 @@ void DrawPlaneEx(Vector3 centerPos, Vector2 size, Vector3 rotation, int slicesX, // Draw the plane quad by quad (with textcoords) rlTexCoord2f((float)x * texPieceW, (float)z * texPieceH); rlVertex3f((float)x * quadWidth, 0.0f, (float)z * quadLenght); - + rlTexCoord2f((float)x * texPieceW + texPieceW, (float)z * texPieceH); rlVertex3f((float)x * quadWidth + quadWidth, 0.0f, (float)z * quadLenght); - + rlTexCoord2f((float)x * texPieceW + texPieceW, (float)z * texPieceH + texPieceH); rlVertex3f((float)x * quadWidth + quadWidth, 0.0f, (float)z * quadLenght + quadLenght); - + rlTexCoord2f((float)x * texPieceW, (float)z * texPieceH + texPieceH); rlVertex3f((float)x * quadWidth, 0.0f, (float)z * quadLenght + quadLenght); } @@ -535,7 +535,7 @@ void DrawGrid(int slices, float spacing) rlColor3f(0.75f, 0.75f, 0.75f); rlColor3f(0.75f, 0.75f, 0.75f); } - + rlVertex3f((float)i*spacing, 0.0f, (float)-halfSlices*spacing); rlVertex3f((float)i*spacing, 0.0f, (float)halfSlices*spacing); @@ -555,22 +555,22 @@ void DrawGizmo(Vector3 position) rlTranslatef(position.x, position.y, position.z); //rlRotatef(rotation, 0, 1, 0); rlScalef(lenght, lenght, lenght); - + rlBegin(RL_LINES); rlColor3f(1.0f, 0.0f, 0.0f); rlVertex3f(0.0f, 0.0f, 0.0f); rlColor3f(1.0f, 0.0f, 0.0f); rlVertex3f(1.0f, 0.0f, 0.0f); - + rlColor3f(0.0f, 1.0f, 0.0f); rlVertex3f(0.0f, 0.0f, 0.0f); rlColor3f(0.0f, 1.0f, 0.0f); rlVertex3f(0.0f, 1.0f, 0.0f); - + rlColor3f(0.0f, 0.0f, 1.0f); rlVertex3f(0.0f, 0.0f, 0.0f); rlColor3f(0.0f, 0.0f, 1.0f); rlVertex3f(0.0f, 0.0f, 1.0f); - rlEnd(); + rlEnd(); rlPopMatrix(); } void DrawGizmoEx(Vector3 position, Vector3 rotation, float scale) -{ +{ // NOTE: RGB = XYZ rlPushMatrix(); rlTranslatef(position.x, position.y, position.z); @@ -581,53 +581,53 @@ void DrawGizmoEx(Vector3 position, Vector3 rotation, float scale) // X Axis rlColor4ub(200, 0, 0, 255); rlVertex3f(position.x, position.y, position.z); rlColor4ub(200, 0, 0, 255); rlVertex3f(position.x + 1, position.y, position.z); - + // ArrowX rlColor4ub(200, 0, 0, 255); rlVertex3f(position.x + 1.1, position.y, position.z); rlColor4ub(200, 0, 0, 255); rlVertex3f(position.x + .9, position.y, position.z + .1); - + rlColor4ub(200, 0, 0, 255); rlVertex3f(position.x + 1.1, position.y, position.z); rlColor4ub(200, 0, 0, 255); rlVertex3f(position.x + .9, position.y, position.z - .1); - + // Y Axis rlColor4ub(0, 200, 0, 255); rlVertex3f(position.x, position.y, position.z); rlColor4ub(0, 200, 0, 255); rlVertex3f(position.x, position.y + 1, position.z); - + // ArrowY rlColor4ub(0, 200, 0, 255); rlVertex3f(position.x, position.y + 1.1, position.z); rlColor4ub(0, 200, 0, 255); rlVertex3f(position.x + .1, position.y + .9, position.z); - + rlColor4ub(0, 200, 0, 255); rlVertex3f(position.x, position.y + 1.1, position.z); rlColor4ub(0, 200, 0, 255); rlVertex3f(position.x - .1, position.y + .9, position.z); - + // Z Axis rlColor4ub(0, 0, 200, 255); rlVertex3f(position.x, position.y, position.z); rlColor4ub(0, 0, 200, 255); rlVertex3f(position.x, position.y, position.z - 1); - + // ArrowZ rlColor4ub(0, 0, 200, 255); rlVertex3f(position.x, position.y, position.z - 1.1); rlColor4ub(0, 0, 200, 255); rlVertex3f(position.x + .1, position.y, position.z - .9); - + rlColor4ub(0, 0, 200, 255); rlVertex3f(position.x, position.y, position.z - 1.1); rlColor4ub(0, 0, 200, 255); rlVertex3f(position.x - .1, position.y, position.z - .9); - + // Extra int n = 3; - + // X Axis for (int i=0; i < 360; i += 6) { rlColor4ub(200, 0, 0, 255); rlVertex3f(0, position.x + sin(DEG2RAD*i) * scale/n, position.y + cos(DEG2RAD*i) * scale/n); rlColor4ub(200, 0, 0, 255); rlVertex3f(0, position.x + sin(DEG2RAD*(i+6)) * scale/n, position.y + cos(DEG2RAD*(i+6)) * scale/n); } - + // Y Axis for (int i=0; i < 360; i += 6) { rlColor4ub(0, 200, 0, 255); rlVertex3f(position.x + sin(DEG2RAD*i) * scale/n, 0, position.y + cos(DEG2RAD*i) * scale/n); rlColor4ub(0, 200, 0, 255); rlVertex3f(position.x + sin(DEG2RAD*(i+6)) * scale/n, 0, position.y + cos(DEG2RAD*(i+6)) * scale/n); } - + // Z Axis for (int i=0; i < 360; i += 6) { @@ -639,18 +639,18 @@ void DrawGizmoEx(Vector3 position, Vector3 rotation, float scale) } // Load a 3d model -Model LoadModel(const char *fileName) +Model LoadModel(const char *fileName) { VertexData vData; - + if (strcmp(GetExtension(fileName),"obj") == 0) vData = LoadOBJ(fileName); - else TraceLog(WARNING, "[%s] Model extension not recognized, it can't be loaded", fileName); + else TraceLog(WARNING, "[%s] Model extension not recognized, it can't be loaded", fileName); Model model; model.mesh = vData; // Model mesh is vertex data model.textureId = 0; - + #if defined(USE_OPENGL_33) || defined(USE_OPENGL_ES2) model.vaoId = rlglLoadModel(vData); // Use loaded data to generate VAO model.textureId = 1; // Default whiteTexture @@ -671,24 +671,24 @@ Model LoadHeightmap(Image heightmap, float maxHeight) int mapX = heightmap.width; int mapZ = heightmap.height; - + // NOTE: One vertex per pixel // TODO: Consider resolution when generating model data? int numTriangles = (mapX-1)*(mapZ-1)*2; // One quad every four pixels - + vData.vertexCount = numTriangles*3; vData.vertices = (float *)malloc(vData.vertexCount * 3 * sizeof(float)); vData.normals = (float *)malloc(vData.vertexCount * 3 * sizeof(float)); vData.texcoords = (float *)malloc(vData.vertexCount * 2 * sizeof(float)); vData.colors = (unsigned char *)malloc(vData.vertexCount * 4 * sizeof(unsigned char)); - + int vCounter = 0; // Used to count vertices float by float int tcCounter = 0; // Used to count texcoords float by float int nCounter = 0; // Used to count normals float by float - + int trisCounter = 0; - + float scaleFactor = maxHeight/255; // TODO: Review scaleFactor calculation for(int z = 0; z < mapZ-1; z++) @@ -697,83 +697,83 @@ Model LoadHeightmap(Image heightmap, float maxHeight) { // Fill vertices array with data //---------------------------------------------------------- - + // one triangle - 3 vertex vData.vertices[vCounter] = x; vData.vertices[vCounter + 1] = GetHeightValue(heightmap.pixels[x + z*mapX])*scaleFactor; vData.vertices[vCounter + 2] = z; - + vData.vertices[vCounter + 3] = x; vData.vertices[vCounter + 4] = GetHeightValue(heightmap.pixels[x + (z+1)*mapX])*scaleFactor; vData.vertices[vCounter + 5] = z+1; - + vData.vertices[vCounter + 6] = x+1; vData.vertices[vCounter + 7] = GetHeightValue(heightmap.pixels[(x+1) + z*mapX])*scaleFactor; vData.vertices[vCounter + 8] = z; - + // another triangle - 3 vertex vData.vertices[vCounter + 9] = vData.vertices[vCounter + 6]; vData.vertices[vCounter + 10] = vData.vertices[vCounter + 7]; vData.vertices[vCounter + 11] = vData.vertices[vCounter + 8]; - + vData.vertices[vCounter + 12] = vData.vertices[vCounter + 3]; vData.vertices[vCounter + 13] = vData.vertices[vCounter + 4]; vData.vertices[vCounter + 14] = vData.vertices[vCounter + 5]; - + vData.vertices[vCounter + 15] = x+1; vData.vertices[vCounter + 16] = GetHeightValue(heightmap.pixels[(x+1) + (z+1)*mapX])*scaleFactor; vData.vertices[vCounter + 17] = z+1; vCounter += 18; // 6 vertex, 18 floats - + // Fill texcoords array with data //-------------------------------------------------------------- vData.texcoords[tcCounter] = (float)x / (mapX-1); vData.texcoords[tcCounter + 1] = (float)z / (mapZ-1); - + vData.texcoords[tcCounter + 2] = (float)x / (mapX-1); vData.texcoords[tcCounter + 3] = (float)(z+1) / (mapZ-1); - + vData.texcoords[tcCounter + 4] = (float)(x+1) / (mapX-1); vData.texcoords[tcCounter + 5] = (float)z / (mapZ-1); - + vData.texcoords[tcCounter + 6] = vData.texcoords[tcCounter + 4]; vData.texcoords[tcCounter + 7] = vData.texcoords[tcCounter + 5]; - + vData.texcoords[tcCounter + 8] = vData.texcoords[tcCounter + 2]; vData.texcoords[tcCounter + 9] = vData.texcoords[tcCounter + 1]; - + vData.texcoords[tcCounter + 10] = (float)(x+1) / (mapX-1); vData.texcoords[tcCounter + 11] = (float)(z+1) / (mapZ-1); tcCounter += 12; // 6 texcoords, 12 floats - + // Fill normals array with data //-------------------------------------------------------------- - // NOTE: Current Model implementation doe not use normals! + // NOTE: Current Model implementation doe not use normals! for (int i = 0; i < 18; i += 3) { vData.normals[nCounter + i] = 0.0f; vData.normals[nCounter + i + 1] = 1.0f; vData.normals[nCounter + i + 2] = 0.0f; } - + // TODO: Calculate normals in an efficient way - + nCounter += 18; // 6 vertex, 18 floats - + trisCounter += 2; } } - + // NOTE: At this point we have all vertex, texcoord, normal data for the model in vData struct // Fill color data for (int i = 0; i < (4*vData.vertexCount); i++) vData.colors[i] = 255; - + Model model; model.mesh = vData; // Model mesh is vertex data model.textureId = 0; - + #if defined(USE_OPENGL_33) || defined(USE_OPENGL_ES2) model.vaoId = rlglLoadModel(vData); // Use loaded data to generate VAO model.textureId = 1; // Default whiteTexture @@ -796,26 +796,26 @@ Model LoadCubesmap(Image cubesmap) float mapCubeSide = 1.0f; int mapWidth = cubesmap.width * (int)mapCubeSide; int mapHeight = cubesmap.height * (int)mapCubeSide; - - // NOTE: Max possible number of triangles numCubes * (12 triangles by cube) + + // NOTE: Max possible number of triangles numCubes * (12 triangles by cube) int maxTriangles = cubesmap.width*cubesmap.height*12; int vCounter = 0; // Used to count vertices int tcCounter = 0; // Used to count texcoords int nCounter = 0; // Used to count normals - + float w = mapCubeSide; float h = mapCubeSide; float h2 = mapCubeSide; - + Vector3 *mapVertices = (Vector3 *)malloc(maxTriangles * 3 * sizeof(Vector3)); Vector2 *mapTexcoords = (Vector2 *)malloc(maxTriangles * 3 * sizeof(Vector2)); - Vector3 *mapNormals = (Vector3 *)malloc(maxTriangles * 3 * sizeof(Vector3)); - + Vector3 *mapNormals = (Vector3 *)malloc(maxTriangles * 3 * sizeof(Vector3)); + for (int z = 0; z < mapHeight; z += mapCubeSide) { for (int x = 0; x < mapWidth; x += mapCubeSide) - { + { // Define the 8 vertex of the cube, we will combine them accordingly later... Vector3 v1 = { x - w/2, h2, z - h/2 }; Vector3 v2 = { x - w/2, h2, z + h/2 }; @@ -825,7 +825,7 @@ Model LoadCubesmap(Image cubesmap) Vector3 v6 = { x - w/2, 0, z - h/2 }; Vector3 v7 = { x - w/2, 0, z + h/2 }; Vector3 v8 = { x + w/2, 0, z + h/2 }; - + // Define the 6 normals of the cube, we will combine them accordingly later... Vector3 n1 = { 1.0f, 0.0f, 0.0f }; Vector3 n2 = { -1.0f, 0.0f, 0.0f }; @@ -833,14 +833,14 @@ Model LoadCubesmap(Image cubesmap) Vector3 n4 = { 0.0f, -1.0f, 0.0f }; Vector3 n5 = { 0.0f, 0.0f, 1.0f }; Vector3 n6 = { 0.0f, 0.0f, -1.0f }; - + // Define the 4 texture coordinates of the cube, we will combine them accordingly later... // TODO: Use texture rectangles to define different textures for top-bottom-front-back-right-left (6) - Vector2 vt2 = { 0.0f, 0.0f }; + Vector2 vt2 = { 0.0f, 0.0f }; Vector2 vt1 = { 0.0f, 1.0f }; Vector2 vt4 = { 1.0f, 0.0f }; Vector2 vt3 = { 1.0f, 1.0f }; - + // We check pixel color to be WHITE, we will full cubes if ((cubesmap.pixels[z*cubesmap.width + x].r == 255) && (cubesmap.pixels[z*cubesmap.width + x].g == 255) && @@ -848,58 +848,58 @@ Model LoadCubesmap(Image cubesmap) { // Define triangles (Checking Collateral Cubes!) //---------------------------------------------- - + // Define top triangles (2 tris, 6 vertex --> v1-v2-v3, v1-v3-v4) mapVertices[vCounter] = v1; - mapVertices[vCounter + 1] = v2; - mapVertices[vCounter + 2] = v3; - mapVertices[vCounter + 3] = v1; - mapVertices[vCounter + 4] = v3; + mapVertices[vCounter + 1] = v2; + mapVertices[vCounter + 2] = v3; + mapVertices[vCounter + 3] = v1; + mapVertices[vCounter + 4] = v3; mapVertices[vCounter + 5] = v4; vCounter += 6; - + mapNormals[nCounter] = n3; - mapNormals[nCounter + 1] = n3; - mapNormals[nCounter + 2] = n3; - mapNormals[nCounter + 3] = n3; - mapNormals[nCounter + 4] = n3; + mapNormals[nCounter + 1] = n3; + mapNormals[nCounter + 2] = n3; + mapNormals[nCounter + 3] = n3; + mapNormals[nCounter + 4] = n3; mapNormals[nCounter + 5] = n3; nCounter += 6; - + mapTexcoords[tcCounter] = vt2; - mapTexcoords[tcCounter + 1] = vt1; - mapTexcoords[tcCounter + 2] = vt3; - mapTexcoords[tcCounter + 3] = vt2; - mapTexcoords[tcCounter + 4] = vt3; + mapTexcoords[tcCounter + 1] = vt1; + mapTexcoords[tcCounter + 2] = vt3; + mapTexcoords[tcCounter + 3] = vt2; + mapTexcoords[tcCounter + 4] = vt3; mapTexcoords[tcCounter + 5] = vt4; tcCounter += 6; - + // Define bottom triangles (2 tris, 6 vertex --> v6-v8-v7, v6-v5-v8) mapVertices[vCounter] = v6; - mapVertices[vCounter + 1] = v8; - mapVertices[vCounter + 2] = v7; - mapVertices[vCounter + 3] = v6; - mapVertices[vCounter + 4] = v5; + mapVertices[vCounter + 1] = v8; + mapVertices[vCounter + 2] = v7; + mapVertices[vCounter + 3] = v6; + mapVertices[vCounter + 4] = v5; mapVertices[vCounter + 5] = v8; vCounter += 6; - + mapNormals[nCounter] = n4; - mapNormals[nCounter + 1] = n4; - mapNormals[nCounter + 2] = n4; - mapNormals[nCounter + 3] = n4; - mapNormals[nCounter + 4] = n4; + mapNormals[nCounter + 1] = n4; + mapNormals[nCounter + 2] = n4; + mapNormals[nCounter + 3] = n4; + mapNormals[nCounter + 4] = n4; mapNormals[nCounter + 5] = n4; nCounter += 6; - + mapTexcoords[tcCounter] = vt4; - mapTexcoords[tcCounter + 1] = vt1; - mapTexcoords[tcCounter + 2] = vt3; - mapTexcoords[tcCounter + 3] = vt4; - mapTexcoords[tcCounter + 4] = vt2; + mapTexcoords[tcCounter + 1] = vt1; + mapTexcoords[tcCounter + 2] = vt3; + mapTexcoords[tcCounter + 3] = vt4; + mapTexcoords[tcCounter + 4] = vt2; mapTexcoords[tcCounter + 5] = vt1; tcCounter += 6; - - if (((z < cubesmap.height - 1) && + + if (((z < cubesmap.height - 1) && (cubesmap.pixels[(z + 1)*cubesmap.width + x].r == 0) && (cubesmap.pixels[(z + 1)*cubesmap.width + x].g == 0) && (cubesmap.pixels[(z + 1)*cubesmap.width + x].b == 0)) || (z == cubesmap.height - 1)) @@ -907,30 +907,30 @@ Model LoadCubesmap(Image cubesmap) // Define front triangles (2 tris, 6 vertex) --> v2 v7 v3, v3 v7 v8 // NOTE: Collateral occluded faces are not generated mapVertices[vCounter] = v2; - mapVertices[vCounter + 1] = v7; - mapVertices[vCounter + 2] = v3; - mapVertices[vCounter + 3] = v3; - mapVertices[vCounter + 4] = v7; + mapVertices[vCounter + 1] = v7; + mapVertices[vCounter + 2] = v3; + mapVertices[vCounter + 3] = v3; + mapVertices[vCounter + 4] = v7; mapVertices[vCounter + 5] = v8; vCounter += 6; - + mapNormals[nCounter] = n6; - mapNormals[nCounter + 1] = n6; - mapNormals[nCounter + 2] = n6; - mapNormals[nCounter + 3] = n6; - mapNormals[nCounter + 4] = n6; + mapNormals[nCounter + 1] = n6; + mapNormals[nCounter + 2] = n6; + mapNormals[nCounter + 3] = n6; + mapNormals[nCounter + 4] = n6; mapNormals[nCounter + 5] = n6; nCounter += 6; - + mapTexcoords[tcCounter] = vt2; - mapTexcoords[tcCounter + 1] = vt1; - mapTexcoords[tcCounter + 2] = vt4; - mapTexcoords[tcCounter + 3] = vt4; - mapTexcoords[tcCounter + 4] = vt1; + mapTexcoords[tcCounter + 1] = vt1; + mapTexcoords[tcCounter + 2] = vt4; + mapTexcoords[tcCounter + 3] = vt4; + mapTexcoords[tcCounter + 4] = vt1; mapTexcoords[tcCounter + 5] = vt3; tcCounter += 6; } - + if (((z > 0) && (cubesmap.pixels[(z - 1)*cubesmap.width + x].r == 0) && (cubesmap.pixels[(z - 1)*cubesmap.width + x].g == 0) && @@ -939,30 +939,30 @@ Model LoadCubesmap(Image cubesmap) // Define back triangles (2 tris, 6 vertex) --> v1 v5 v6, v1 v4 v5 // NOTE: Collateral occluded faces are not generated mapVertices[vCounter] = v1; - mapVertices[vCounter + 1] = v5; - mapVertices[vCounter + 2] = v6; - mapVertices[vCounter + 3] = v1; - mapVertices[vCounter + 4] = v4; + mapVertices[vCounter + 1] = v5; + mapVertices[vCounter + 2] = v6; + mapVertices[vCounter + 3] = v1; + mapVertices[vCounter + 4] = v4; mapVertices[vCounter + 5] = v5; vCounter += 6; - + mapNormals[nCounter] = n5; - mapNormals[nCounter + 1] = n5; - mapNormals[nCounter + 2] = n5; - mapNormals[nCounter + 3] = n5; - mapNormals[nCounter + 4] = n5; + mapNormals[nCounter + 1] = n5; + mapNormals[nCounter + 2] = n5; + mapNormals[nCounter + 3] = n5; + mapNormals[nCounter + 4] = n5; mapNormals[nCounter + 5] = n5; nCounter += 6; - + mapTexcoords[tcCounter] = vt4; - mapTexcoords[tcCounter + 1] = vt1; - mapTexcoords[tcCounter + 2] = vt3; - mapTexcoords[tcCounter + 3] = vt4; - mapTexcoords[tcCounter + 4] = vt2; + mapTexcoords[tcCounter + 1] = vt1; + mapTexcoords[tcCounter + 2] = vt3; + mapTexcoords[tcCounter + 3] = vt4; + mapTexcoords[tcCounter + 4] = vt2; mapTexcoords[tcCounter + 5] = vt1; tcCounter += 6; } - + if (((x < cubesmap.width - 1) && (cubesmap.pixels[z*cubesmap.width + (x + 1)].r == 0) && (cubesmap.pixels[z*cubesmap.width + (x + 1)].g == 0) && @@ -971,30 +971,30 @@ Model LoadCubesmap(Image cubesmap) // Define right triangles (2 tris, 6 vertex) --> v3 v8 v4, v4 v8 v5 // NOTE: Collateral occluded faces are not generated mapVertices[vCounter] = v3; - mapVertices[vCounter + 1] = v8; - mapVertices[vCounter + 2] = v4; - mapVertices[vCounter + 3] = v4; - mapVertices[vCounter + 4] = v8; + mapVertices[vCounter + 1] = v8; + mapVertices[vCounter + 2] = v4; + mapVertices[vCounter + 3] = v4; + mapVertices[vCounter + 4] = v8; mapVertices[vCounter + 5] = v5; vCounter += 6; - + mapNormals[nCounter] = n1; - mapNormals[nCounter + 1] = n1; - mapNormals[nCounter + 2] = n1; - mapNormals[nCounter + 3] = n1; - mapNormals[nCounter + 4] = n1; + mapNormals[nCounter + 1] = n1; + mapNormals[nCounter + 2] = n1; + mapNormals[nCounter + 3] = n1; + mapNormals[nCounter + 4] = n1; mapNormals[nCounter + 5] = n1; nCounter += 6; - + mapTexcoords[tcCounter] = vt2; - mapTexcoords[tcCounter + 1] = vt1; - mapTexcoords[tcCounter + 2] = vt4; - mapTexcoords[tcCounter + 3] = vt4; - mapTexcoords[tcCounter + 4] = vt1; + mapTexcoords[tcCounter + 1] = vt1; + mapTexcoords[tcCounter + 2] = vt4; + mapTexcoords[tcCounter + 3] = vt4; + mapTexcoords[tcCounter + 4] = vt1; mapTexcoords[tcCounter + 5] = vt3; tcCounter += 6; } - + if (((x > 0) && (cubesmap.pixels[z*cubesmap.width + (x - 1)].r == 0) && (cubesmap.pixels[z*cubesmap.width + (x - 1)].g == 0) && @@ -1003,26 +1003,26 @@ Model LoadCubesmap(Image cubesmap) // Define left triangles (2 tris, 6 vertex) --> v1 v7 v2, v1 v6 v7 // NOTE: Collateral occluded faces are not generated mapVertices[vCounter] = v1; - mapVertices[vCounter + 1] = v7; - mapVertices[vCounter + 2] = v2; - mapVertices[vCounter + 3] = v1; - mapVertices[vCounter + 4] = v6; + mapVertices[vCounter + 1] = v7; + mapVertices[vCounter + 2] = v2; + mapVertices[vCounter + 3] = v1; + mapVertices[vCounter + 4] = v6; mapVertices[vCounter + 5] = v7; vCounter += 6; - + mapNormals[nCounter] = n2; - mapNormals[nCounter + 1] = n2; - mapNormals[nCounter + 2] = n2; - mapNormals[nCounter + 3] = n2; - mapNormals[nCounter + 4] = n2; + mapNormals[nCounter + 1] = n2; + mapNormals[nCounter + 2] = n2; + mapNormals[nCounter + 3] = n2; + mapNormals[nCounter + 4] = n2; mapNormals[nCounter + 5] = n2; nCounter += 6; - + mapTexcoords[tcCounter] = vt2; - mapTexcoords[tcCounter + 1] = vt3; - mapTexcoords[tcCounter + 2] = vt4; - mapTexcoords[tcCounter + 3] = vt2; - mapTexcoords[tcCounter + 4] = vt1; + mapTexcoords[tcCounter + 1] = vt3; + mapTexcoords[tcCounter + 2] = vt4; + mapTexcoords[tcCounter + 3] = vt2; + mapTexcoords[tcCounter + 4] = vt1; mapTexcoords[tcCounter + 5] = vt3; tcCounter += 6; } @@ -1034,28 +1034,28 @@ Model LoadCubesmap(Image cubesmap) { // Define top triangles (2 tris, 6 vertex --> v1-v3-v2, v1-v4-v3) // TODO: ... - - // Define bottom triangles (2 tris, 6 vertex --> v6-v7-v8, v6-v8-v5) + + // Define bottom triangles (2 tris, 6 vertex --> v6-v7-v8, v6-v8-v5) // TODO: ... } - } + } } // Move data from mapVertices temp arays to vertices float array vData.vertexCount = vCounter; - + printf("Vertex count: %i\n", vCounter); vData.vertices = (float *)malloc(vData.vertexCount * 3 * sizeof(float)); vData.normals = (float *)malloc(vData.vertexCount * 3 * sizeof(float)); vData.texcoords = (float *)malloc(vData.vertexCount * 2 * sizeof(float)); vData.colors = (unsigned char *)malloc(vData.vertexCount * 4 * sizeof(unsigned char)); - + // Fill color data for (int i = 0; i < (4*vData.vertexCount); i++) vData.colors[i] = 255; - + int fCounter = 0; - + // Move vertices data for (int i = 0; i < vCounter; i++) { @@ -1064,9 +1064,9 @@ Model LoadCubesmap(Image cubesmap) vData.vertices[fCounter + 2] = mapVertices[i].z; fCounter += 3; } - + fCounter = 0; - + // Move normals data for (int i = 0; i < nCounter; i++) { @@ -1075,9 +1075,9 @@ Model LoadCubesmap(Image cubesmap) vData.normals[fCounter + 2] = mapNormals[i].z; fCounter += 3; } - + fCounter = 0; - + // Move texcoords data for (int i = 0; i < tcCounter; i++) { @@ -1085,18 +1085,18 @@ Model LoadCubesmap(Image cubesmap) vData.texcoords[fCounter + 1] = mapTexcoords[i].y; fCounter += 2; } - + free(mapVertices); free(mapNormals); free(mapTexcoords); - + // NOTE: At this point we have all vertex, texcoord, normal data for the model in vData struct - + Model model; model.mesh = vData; // Model mesh is vertex data model.textureId = 0; - + #if defined(USE_OPENGL_33) || defined(USE_OPENGL_ES2) model.vaoId = rlglLoadModel(vData); // Use loaded data to generate VAO model.textureId = 1; // Default whiteTexture @@ -1106,7 +1106,7 @@ Model LoadCubesmap(Image cubesmap) //free(vData.texcoords); //free(vData.normals); #endif - + return model; } @@ -1157,22 +1157,22 @@ void DrawBillboard(Camera camera, Texture2D texture, Vector3 center, float size, { // NOTE: Billboard size will maintain texture aspect ratio, size will be billboard width Vector2 sizeRatio = { size, size * (float)texture.height/texture.width }; - + Matrix viewMatrix = MatrixLookAt(camera.position, camera.target, camera.up); MatrixTranspose(&viewMatrix); - + Vector3 right = { viewMatrix.m0, viewMatrix.m4, viewMatrix.m8 }; Vector3 up = { viewMatrix.m1, viewMatrix.m5, viewMatrix.m9 }; -/* +/* d-------c | | | * | | | a-------b -*/ +*/ VectorScale(&right, sizeRatio.x/2); VectorScale(&up, sizeRatio.y/2); - + Vector3 p1 = VectorAdd(right, up); Vector3 p2 = VectorSubtract(right, up); @@ -1180,18 +1180,18 @@ void DrawBillboard(Camera camera, Texture2D texture, Vector3 center, float size, Vector3 b = VectorAdd(center, p1); Vector3 c = VectorAdd(center, p2); Vector3 d = VectorSubtract(center, p1); - + rlEnableTexture(texture.id); - + rlBegin(RL_QUADS); rlColor4ub(tint.r, tint.g, tint.b, tint.a); - rlNormal3f(0.0f, 1.0f, 0.0f); + rlNormal3f(0.0f, 1.0f, 0.0f); rlTexCoord2f(0.0f, 0.0f); rlVertex3f(a.x, a.y, a.z); rlTexCoord2f(1.0f, 0.0f); rlVertex3f(b.x, b.y, b.z); rlTexCoord2f(1.0f, 1.0f); rlVertex3f(c.x, c.y, c.z); rlTexCoord2f(0.0f, 1.0f); rlVertex3f(d.x, d.y, d.z); rlEnd(); - + rlDisableTexture(); } @@ -1203,16 +1203,16 @@ void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle sourceRec, Vec Matrix viewMatrix = MatrixLookAt(camera.position, camera.target, camera.up); MatrixTranspose(&viewMatrix); - + Vector3 right = { viewMatrix.m0, viewMatrix.m4, viewMatrix.m8 }; Vector3 up = { viewMatrix.m1, viewMatrix.m5, viewMatrix.m9 }; -/* +/* d-------c | | | * | | | a-------b -*/ +*/ VectorScale(&right, sizeRatio.x/2); VectorScale(&up, sizeRatio.y/2); @@ -1223,29 +1223,29 @@ void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle sourceRec, Vec Vector3 b = VectorAdd(center, p1); Vector3 c = VectorAdd(center, p2); Vector3 d = VectorSubtract(center, p1); - + rlEnableTexture(texture.id); - + rlBegin(RL_QUADS); rlColor4ub(tint.r, tint.g, tint.b, tint.a); - + // 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); rlVertex3f(a.x, a.y, a.z); - + // Bottom-right corner for texture and quad rlTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)sourceRec.y / texture.height); rlVertex3f(b.x, b.y, b.z); - + // 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); rlVertex3f(c.x, c.y, c.z); - + // Top-left corner for texture and quad rlTexCoord2f((float)sourceRec.x / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height); rlVertex3f(d.x, d.y, d.z); rlEnd(); - + rlDisableTexture(); } @@ -1259,10 +1259,10 @@ static float GetHeightValue(Color pixel) static VertexData LoadOBJ(const char *fileName) { VertexData vData; - + char dataType; char comments[200]; - + int numVertex = 0; int numNormals = 0; int numTexCoords = 0; @@ -1271,14 +1271,14 @@ static VertexData LoadOBJ(const char *fileName) FILE* objFile; objFile = fopen(fileName, "rt"); - + // First reading pass: Get numVertex, numNormals, numTexCoords, numTriangles // NOTE: vertex, texcoords and normals could be optimized (to be used indexed on faces definition) // NOTE: faces MUST be defined as TRIANGLES, not QUADS while(!feof(objFile)) { fscanf(objFile, "%c", &dataType); - + switch(dataType) { case '#': // Comments @@ -1288,12 +1288,12 @@ static VertexData LoadOBJ(const char *fileName) case 'm': // mtllib [external .mtl file name] case 'u': // usemtl [material name] { - fgets(comments, 200, objFile); - } break; + fgets(comments, 200, objFile); + } break; case 'v': { fscanf(objFile, "%c", &dataType); - + if (dataType == 't') // Read texCoord { numTexCoords++; @@ -1318,12 +1318,12 @@ static VertexData LoadOBJ(const char *fileName) default: break; } } - + TraceLog(DEBUG, "[%s] Model num vertices: %i", fileName, numVertex); TraceLog(DEBUG, "[%s] Model num texcoords: %i", fileName, numTexCoords); TraceLog(DEBUG, "[%s] Model num normals: %i", fileName, numNormals); TraceLog(DEBUG, "[%s] Model num triangles: %i", fileName, numTriangles); - + // Once we know the number of vertices to store, we create required arrays Vector3 *midVertices = (Vector3 *)malloc(numVertex*sizeof(Vector3)); Vector3 *midNormals; @@ -1336,86 +1336,86 @@ static VertexData LoadOBJ(const char *fileName) int countTexCoords = 0; rewind(objFile); // Return to the beginning of the file, to read again - + // Second reading pass: Get vertex data to fill intermediate arrays // NOTE: This second pass is required in case of multiple meshes defined in same OBJ // TODO: Consider that diferent meshes can have different vertex data available (position, texcoords, normals) while(!feof(objFile)) { fscanf(objFile, "%c", &dataType); - + switch(dataType) { - case '#': case 'o': case 'g': case 's': case 'm': case 'u': case 'f': fgets(comments, 200, objFile); break; - case 'v': + case '#': case 'o': case 'g': case 's': case 'm': case 'u': case 'f': fgets(comments, 200, objFile); break; + case 'v': { fscanf(objFile, "%c", &dataType); - + if (dataType == 't') // Read texCoord { float useless = 0; - + fscanf(objFile, "%f %f %f", &midTexCoords[countTexCoords].x, &midTexCoords[countTexCoords].y, &useless); countTexCoords++; - + fscanf(objFile, "%c", &dataType); } else if (dataType == 'n') // Read normals { fscanf(objFile, "%f %f %f", &midNormals[countNormals].x, &midNormals[countNormals].y, &midNormals[countNormals].z ); countNormals++; - + fscanf(objFile, "%c", &dataType); } else // Read vertex { fscanf(objFile, "%f %f %f", &midVertices[countVertex].x, &midVertices[countVertex].y, &midVertices[countVertex].z ); countVertex++; - + fscanf(objFile, "%c", &dataType); } } break; default: break; } } - + // At this point all vertex data (v, vt, vn) has been gathered on midVertices, midTexCoords, midNormals // Now we can organize that data into our VertexData struct - + vData.vertexCount = numTriangles*3; - + // Additional arrays to store vertex data as floats vData.vertices = (float *)malloc(vData.vertexCount * 3 * sizeof(float)); vData.texcoords = (float *)malloc(vData.vertexCount * 2 * sizeof(float)); vData.normals = (float *)malloc(vData.vertexCount * 3 * sizeof(float)); vData.colors = (unsigned char *)malloc(vData.vertexCount * 4 * sizeof(unsigned char)); - + int vCounter = 0; // Used to count vertices float by float int tcCounter = 0; // Used to count texcoords float by float int nCounter = 0; // Used to count normals float by float - + int vNum[3], vtNum[3], vnNum[3]; - + rewind(objFile); // Return to the beginning of the file, to read again - + if (numNormals == 0) TraceLog(INFO, "[%s] No normals data on OBJ, normals will be generated from faces data", fileName); - + // Third reading pass: Get faces (triangles) data and fill VertexArray while(!feof(objFile)) { fscanf(objFile, "%c", &dataType); - + switch(dataType) { - case '#': case 'o': case 'g': case 's': case 'm': case 'u': case 'v': fgets(comments, 200, objFile); break; + case '#': case 'o': case 'g': case 's': case 'm': case 'u': case 'v': fgets(comments, 200, objFile); break; case 'f': { // NOTE: It could be that OBJ does not have normals or texcoords defined! - + if ((numNormals == 0) && (numTexCoords == 0)) fscanf(objFile, "%i %i %i", &vNum[0], &vNum[1], &vNum[2]); else if (numNormals == 0) fscanf(objFile, "%i/%i %i/%i %i/%i", &vNum[0], &vtNum[0], &vNum[1], &vtNum[1], &vNum[2], &vtNum[2]); else fscanf(objFile, "%i/%i/%i %i/%i/%i %i/%i/%i", &vNum[0], &vtNum[0], &vnNum[0], &vNum[1], &vtNum[1], &vnNum[1], &vNum[2], &vtNum[2], &vnNum[2]); - + vData.vertices[vCounter] = midVertices[vNum[0]-1].x; vData.vertices[vCounter + 1] = midVertices[vNum[0]-1].y; vData.vertices[vCounter + 2] = midVertices[vNum[0]-1].z; @@ -1428,7 +1428,7 @@ static VertexData LoadOBJ(const char *fileName) vData.vertices[vCounter + 1] = midVertices[vNum[2]-1].y; vData.vertices[vCounter + 2] = midVertices[vNum[2]-1].z; vCounter += 3; - + if (numNormals > 0) { vData.normals[nCounter] = midNormals[vnNum[0]-1].x; @@ -1449,7 +1449,7 @@ static VertexData LoadOBJ(const char *fileName) // If normals not defined, they are calculated from the 3 vertices [N = (V2 - V1) x (V3 - V1)] Vector3 norm = VectorCrossProduct(VectorSubtract(midVertices[vNum[1]-1], midVertices[vNum[0]-1]), VectorSubtract(midVertices[vNum[2]-1], midVertices[vNum[0]-1])); VectorNormalize(&norm); - + vData.normals[nCounter] = norm.x; vData.normals[nCounter + 1] = norm.y; vData.normals[nCounter + 2] = norm.z; @@ -1463,7 +1463,7 @@ static VertexData LoadOBJ(const char *fileName) vData.normals[nCounter + 2] = norm.z; nCounter += 3; } - + if (numTexCoords > 0) { vData.texcoords[tcCounter] = midTexCoords[vtNum[0]-1].x; @@ -1480,22 +1480,22 @@ static VertexData LoadOBJ(const char *fileName) default: break; } } - + fclose(objFile); - + // Security check, just in case no normals or no texcoords defined in OBJ if (numTexCoords == 0) for (int i = 0; i < (2*vData.vertexCount); i++) vData.texcoords[i] = 0.0f; - + // NOTE: We set all vertex colors to white for (int i = 0; i < (4*vData.vertexCount); i++) vData.colors[i] = 255; - + // Now we can free temp mid* arrays free(midVertices); free(midNormals); free(midTexCoords); - + // NOTE: At this point we have all vertex, texcoord, normal data for the model in vData struct TraceLog(INFO, "[%s] Model loaded successfully in RAM (CPU)", fileName); - + return vData; } \ No newline at end of file diff --git a/src/raylib.h b/src/raylib.h index da5427c0..472a0b94 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -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) diff --git a/src/raymath.c b/src/raymath.c index af39da34..35774a57 100644 --- a/src/raymath.c +++ b/src/raymath.c @@ -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; } \ No newline at end of file diff --git a/src/raymath.h b/src/raymath.h index ec7aede3..3296681f 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -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 diff --git a/src/rlgl.c b/src/rlgl.c index 75978e11..4ffb98fc 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -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+ -* +* * 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 @@ -41,10 +41,10 @@ #ifdef USE_OPENGL_33 #undef USE_OPENGL_33 #endif - + #ifdef USE_OPENGL_ES2 #undef USE_OPENGL_ES2 - #endif + #endif #endif #ifdef USE_OPENGL_11 @@ -52,7 +52,7 @@ #endif #ifdef USE_OPENGL_33 - #define GLEW_STATIC + #define GLEW_STATIC #include // Extensions loading lib #endif @@ -148,7 +148,7 @@ static VertexPositionColorBuffer triangles; // No texture support static VertexPositionColorTextureIndexBuffer quads; // Vetex-Fragment Shader Program ID -static GLuint shaderProgram; +static GLuint shaderProgram; // Shader program attibutes binding locations static GLuint vertexLoc, texcoordLoc, colorLoc; @@ -202,25 +202,25 @@ static pixel *GenNextMipmap(pixel *srcData, int srcWidth, int srcHeight); // Fallback to OpenGL 1.1 function calls //--------------------------------------- -void rlMatrixMode(int mode) -{ - switch (mode) +void rlMatrixMode(int mode) +{ + switch (mode) { case RL_PROJECTION: glMatrixMode(GL_PROJECTION); break; - case RL_MODELVIEW: glMatrixMode(GL_MODELVIEW); break; + case RL_MODELVIEW: glMatrixMode(GL_MODELVIEW); break; case RL_TEXTURE: glMatrixMode(GL_TEXTURE); break; default: break; } } -void rlFrustum(double left, double right, double bottom, double top, double near, double far) -{ - glFrustum(left, right, bottom, top, near, far); +void rlFrustum(double left, double right, double bottom, double top, double near, double far) +{ + glFrustum(left, right, bottom, top, near, far); } -void rlOrtho(double left, double right, double bottom, double top, double near, double far) -{ - glOrtho(left, right, bottom, top, near, far); +void rlOrtho(double left, double right, double bottom, double top, double near, double far) +{ + glOrtho(left, right, bottom, top, near, far); } void rlPushMatrix() { glPushMatrix(); } @@ -239,7 +239,7 @@ void rlMatrixMode(int mode) if (mode == RL_PROJECTION) currentMatrix = &projection; else if (mode == RL_MODELVIEW) currentMatrix = &modelview; //else if (mode == RL_TEXTURE) // Not supported - + currentMatrixMode = mode; } @@ -254,7 +254,7 @@ void rlPushMatrix() stack[stackCounter] = *currentMatrix; rlLoadIdentity(); stackCounter++; - + if (currentMatrixMode == RL_MODELVIEW) useTempBuffer = true; } @@ -262,8 +262,8 @@ void rlPushMatrix() void rlPopMatrix() { if (stackCounter > 0) - { - Matrix mat = stack[stackCounter - 1]; + { + Matrix mat = stack[stackCounter - 1]; *currentMatrix = mat; stackCounter--; } @@ -280,7 +280,7 @@ void rlTranslatef(float x, float y, float z) { Matrix mat = MatrixTranslate(x, y, z); MatrixTranspose(&mat); - + *currentMatrix = MatrixMultiply(*currentMatrix, mat); } @@ -289,13 +289,13 @@ void rlRotatef(float angleDeg, float x, float y, float z) { // TODO: Support rotation in multiple axes Matrix rot = MatrixIdentity(); - + if (x == 1) rot = MatrixRotateX(angleDeg*DEG2RAD); else if (y == 1) rot = MatrixRotateY(angleDeg*DEG2RAD); else if (z == 1) rot = MatrixRotateZ(angleDeg*DEG2RAD); - + MatrixTranspose(&rot); - + *currentMatrix = MatrixMultiply(*currentMatrix, rot); } @@ -304,7 +304,7 @@ void rlScalef(float x, float y, float z) { Matrix mat = MatrixScale(x, y, z); MatrixTranspose(&mat); - + *currentMatrix = MatrixMultiply(*currentMatrix, mat); } @@ -330,11 +330,11 @@ void rlFrustum(double left, double right, double bottom, double top, double near } // Multiply the current matrix by an orthographic matrix generated by parameters -void rlOrtho(double left, double right, double bottom, double top, double near, double far) +void rlOrtho(double left, double right, double bottom, double top, double near, double far) { Matrix matOrtho = MatrixOrtho(left, right, bottom, top, near, far); MatrixTranspose(&matOrtho); - + *currentMatrix = MatrixMultiply(*currentMatrix, matOrtho); } @@ -347,7 +347,7 @@ void rlOrtho(double left, double right, double bottom, double top, double near, // Fallback to OpenGL 1.1 function calls //--------------------------------------- -void rlBegin(int mode) +void rlBegin(int mode) { switch (mode) { @@ -388,13 +388,13 @@ void rlEnd() // Apply transformation matrix to all temp vertices for (int i = 0; i < tempBufferCount; i++) VectorTransform(&tempBuffer[i], *currentMatrix); - + // Deactivate tempBuffer usage to allow rlVertex3f do its job useTempBuffer = false; - + // Copy all transformed vertices to right VAO for (int i = 0; i < tempBufferCount; i++) rlVertex3f(tempBuffer[i].x, tempBuffer[i].y, tempBuffer[i].z); - + // Reset temp buffer tempBufferCount = 0; } @@ -408,14 +408,14 @@ void rlEnd() if (lines.vCounter != lines.cCounter) { int addColors = lines.vCounter - lines.cCounter; - + for (int i = 0; i < addColors; i++) { lines.colors[4*lines.cCounter] = lines.colors[4*lines.cCounter - 4]; lines.colors[4*lines.cCounter + 1] = lines.colors[4*lines.cCounter - 3]; lines.colors[4*lines.cCounter + 2] = lines.colors[4*lines.cCounter - 2]; lines.colors[4*lines.cCounter + 3] = lines.colors[4*lines.cCounter - 1]; - + lines.cCounter++; } } @@ -425,17 +425,17 @@ void rlEnd() if (triangles.vCounter != triangles.cCounter) { int addColors = triangles.vCounter - triangles.cCounter; - + for (int i = 0; i < addColors; i++) { triangles.colors[4*triangles.cCounter] = triangles.colors[4*triangles.cCounter - 4]; triangles.colors[4*triangles.cCounter + 1] = triangles.colors[4*triangles.cCounter - 3]; triangles.colors[4*triangles.cCounter + 2] = triangles.colors[4*triangles.cCounter - 2]; triangles.colors[4*triangles.cCounter + 3] = triangles.colors[4*triangles.cCounter - 1]; - + triangles.cCounter++; } - } + } } break; case RL_QUADS: { @@ -443,14 +443,14 @@ void rlEnd() if (quads.vCounter != quads.cCounter) { int addColors = quads.vCounter - quads.cCounter; - + for (int i = 0; i < addColors; i++) { quads.colors[4*quads.cCounter] = quads.colors[4*quads.cCounter - 4]; quads.colors[4*quads.cCounter + 1] = quads.colors[4*quads.cCounter - 3]; quads.colors[4*quads.cCounter + 2] = quads.colors[4*quads.cCounter - 2]; quads.colors[4*quads.cCounter + 3] = quads.colors[4*quads.cCounter - 1]; - + quads.cCounter++; } } @@ -459,18 +459,18 @@ void rlEnd() if (quads.vCounter != quads.tcCounter) { int addTexCoords = quads.vCounter - quads.tcCounter; - + for (int i = 0; i < addTexCoords; i++) { quads.texcoords[2*quads.tcCounter] = 0.0f; quads.texcoords[2*quads.tcCounter + 1] = 0.0f; - + quads.tcCounter++; } } - + // TODO: Make sure normals count match vertex count - + } break; default: break; } @@ -495,29 +495,29 @@ void rlVertex3f(float x, float y, float z) lines.vertices[3*lines.vCounter] = x; lines.vertices[3*lines.vCounter + 1] = y; lines.vertices[3*lines.vCounter + 2] = z; - + lines.vCounter++; - + } break; case RL_TRIANGLES: { triangles.vertices[3*triangles.vCounter] = x; triangles.vertices[3*triangles.vCounter + 1] = y; triangles.vertices[3*triangles.vCounter + 2] = z; - + triangles.vCounter++; - + } break; case RL_QUADS: { quads.vertices[3*quads.vCounter] = x; quads.vertices[3*quads.vCounter + 1] = y; quads.vertices[3*quads.vCounter + 2] = z; - + quads.vCounter++; - + draws[drawsCounter - 1].vertexCount++; - + } break; default: break; } @@ -567,9 +567,9 @@ void rlColor4ub(byte x, byte y, byte z, byte w) lines.colors[4*lines.cCounter + 1] = y; lines.colors[4*lines.cCounter + 2] = z; lines.colors[4*lines.cCounter + 3] = w; - + lines.cCounter++; - + } break; case RL_TRIANGLES: { @@ -577,9 +577,9 @@ void rlColor4ub(byte x, byte y, byte z, byte w) triangles.colors[4*triangles.cCounter + 1] = y; triangles.colors[4*triangles.cCounter + 2] = z; triangles.colors[4*triangles.cCounter + 3] = w; - + triangles.cCounter++; - + } break; case RL_QUADS: { @@ -587,9 +587,9 @@ void rlColor4ub(byte x, byte y, byte z, byte w) quads.colors[4*quads.cCounter + 1] = y; quads.colors[4*quads.cCounter + 2] = z; quads.colors[4*quads.cCounter + 3] = w; - + quads.cCounter++; - + } break; default: break; } @@ -598,7 +598,7 @@ void rlColor4ub(byte x, byte y, byte z, byte w) // Define one vertex (color) void rlColor4f(float r, float g, float b, float a) { - rlColor4ub((byte)(r*255), (byte)(g*255), (byte)(b*255), (byte)(a*255)); + rlColor4ub((byte)(r*255), (byte)(g*255), (byte)(b*255), (byte)(a*255)); } // Define one vertex (color) @@ -625,7 +625,7 @@ void rlEnableTexture(unsigned int id) if (draws[drawsCounter - 1].textureId != id) { if (draws[drawsCounter - 1].vertexCount > 0) drawsCounter++; - + draws[drawsCounter - 1].textureId = id; draws[drawsCounter - 1].vertexCount = 0; } @@ -682,84 +682,84 @@ void rlClearScreenBuffers() // Init OpenGL 3.3+ required data void rlglInit() -{ +{ // Initialize GLEW glewExperimental = 1; // Needed for core profile GLenum error = glewInit(); - - if (error != GLEW_OK) + + if (error != GLEW_OK) { TraceLog(ERROR, "Failed to initialize GLEW - Error Code: %s\n", glewGetErrorString(error)); } if (glewIsSupported("GL_VERSION_3_3")) TraceLog(INFO, "OpenGL 3.3 initialized successfully\n"); - + // Print OpenGL and GLSL version TraceLog(INFO, "Vendor: %s", glGetString(GL_VENDOR)); TraceLog(INFO, "Renderer: %s", glGetString(GL_RENDERER)); TraceLog(INFO, "Version: %s", glGetString(GL_VERSION)); TraceLog(INFO, "GLSL: %s\n", glGetString(0x8B8C)); //GL_SHADING_LANGUAGE_VERSION - + /* // TODO: GLEW is a big library that loads ALL extensions, maybe using glad we can only load required ones... - if (!gladLoadGL()) + if (!gladLoadGL()) { TraceLog("ERROR: Failed to initialize glad\n"); } -*/ +*/ // Set default draw mode currentDrawMode = RL_TRIANGLES; - + // Reset projection and modelview matrices projection = MatrixIdentity(); modelview = MatrixIdentity(); currentMatrix = &modelview; - + // Initialize matrix stack for (int i = 0; i < MATRIX_STACK_SIZE; i++) stack[i] = MatrixIdentity(); // Init default Shader (GLSL 110) -> Common for GL 3.3+ and ES2 shaderProgram = LoadDefaultShaders(); //shaderProgram = LoadShaders("simple150.vert", "simple150.frag"); - + // Get handles to GLSL input vars locations vertexLoc = glGetAttribLocation(shaderProgram, "vertexPosition"); texcoordLoc = glGetAttribLocation(shaderProgram, "vertexTexCoord"); colorLoc = glGetAttribLocation(shaderProgram, "vertexColor"); - + // Get handles to GLSL uniform vars locations (vertex-shader) modelviewMatrixLoc = glGetUniformLocation(shaderProgram, "modelviewMatrix"); projectionMatrixLoc = glGetUniformLocation(shaderProgram, "projectionMatrix"); - + // Get handles to GLSL uniform vars locations (fragment-shader) textureLoc = glGetUniformLocation(shaderProgram, "texture0"); - + InitializeBuffers(); // Init vertex arrays InitializeVAOs(); // Init VBO and VAO - + // Init temp vertex buffer, used when transformation required (translate, rotate, scale) tempBuffer = (Vector3 *)malloc(sizeof(Vector3)*TEMP_VERTEX_BUFFER_SIZE); - + for (int i = 0; i < TEMP_VERTEX_BUFFER_SIZE; i++) tempBuffer[i] = VectorZero(); - + // Create default white texture for plain colors (required by shader) unsigned char pixels[4] = { 255, 255, 255, 255 }; // 1 pixel RGBA (4 bytes) - + whiteTexture = rlglLoadTexture(pixels, 1, 1, false); - + if (whiteTexture != 0) TraceLog(INFO, "[ID %i] Base white texture created successfully", whiteTexture); else TraceLog(WARNING, "Base white texture could not be created"); - + // Init draw calls tracking system draws = (DrawCall *)malloc(sizeof(DrawCall)*MAX_DRAWS_BY_TEXTURE); - + for (int i = 0; i < MAX_DRAWS_BY_TEXTURE; i++) { draws[i].textureId = 0; draws[i].vertexCount = 0; } - + drawsCounter = 1; draws[drawsCounter - 1].textureId = whiteTexture; } @@ -804,39 +804,39 @@ void rlglClose() free(triangles.vertices); free(triangles.colors); - + free(quads.vertices); free(quads.texcoords); free(quads.colors); - + // Free GPU texture glDeleteTextures(1, &whiteTexture); - + free(draws); } void rlglDraw() { UpdateBuffers(); - + glUseProgram(shaderProgram); // Use our shader - + glUniformMatrix4fv(projectionMatrixLoc, 1, false, GetMatrixVector(projection)); glUniformMatrix4fv(modelviewMatrixLoc, 1, false, GetMatrixVector(modelview)); glUniform1i(textureLoc, 0); - - // NOTE: We draw in this order: triangle shapes, textured quads and lines - + + // NOTE: We draw in this order: triangle shapes, textured quads and lines + if (triangles.vCounter > 0) { glBindTexture(GL_TEXTURE_2D, whiteTexture); - + glBindVertexArray(vaoTriangles); glDrawArrays(GL_TRIANGLES, 0, triangles.vCounter); - + glBindTexture(GL_TEXTURE_2D, 0); } - + if (quads.vCounter > 0) { int quadsCount = 0; @@ -844,51 +844,51 @@ void rlglDraw() int indicesOffset = 0; glBindVertexArray(vaoQuads); - + //TraceLog(DEBUG, "Draws required per frame: %i", drawsCounter); - + for (int i = 0; i < drawsCounter; i++) { quadsCount = draws[i].vertexCount/4; numIndicesToProcess = quadsCount*6; // Get number of Quads * 6 index by Quad - + //TraceLog(DEBUG, "Quads to render: %i - Vertex Count: %i", quadsCount, draws[i].vertexCount); glBindTexture(GL_TEXTURE_2D, draws[i].textureId); - + // NOTE: The final parameter tells the GPU the offset in bytes from the start of the index buffer to the location of the first index to process glDrawElements(GL_TRIANGLES, numIndicesToProcess, GL_UNSIGNED_INT, (GLvoid*) (sizeof(GLuint) * indicesOffset)); indicesOffset += draws[i].vertexCount/4*6; } - - glBindTexture(GL_TEXTURE_2D, 0); // Unbind textures + + glBindTexture(GL_TEXTURE_2D, 0); // Unbind textures } - + if (lines.vCounter > 0) { glBindTexture(GL_TEXTURE_2D, whiteTexture); - + glBindVertexArray(vaoLines); glDrawArrays(GL_LINES, 0, lines.vCounter); - + glBindTexture(GL_TEXTURE_2D, 0); } - + glBindVertexArray(0); // Unbind VAO - + // Reset draws counter drawsCounter = 1; draws[0].textureId = whiteTexture; draws[0].vertexCount = 0; - + // Reset vertex counters for next frame lines.vCounter = 0; lines.cCounter = 0; - + triangles.vCounter = 0; triangles.cCounter = 0; - + quads.vCounter = 0; quads.tcCounter = 0; quads.cCounter = 0; @@ -900,7 +900,7 @@ void rlglDraw() void rlglDrawModel(Model model, Vector3 position, Vector3 rotation, Vector3 scale, Color color, bool wires) { if (wires) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - + #ifdef USE_OPENGL_11 glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, model.textureId); @@ -909,48 +909,48 @@ void rlglDrawModel(Model model, Vector3 position, Vector3 rotation, Vector3 scal glEnableClientState(GL_VERTEX_ARRAY); // Enable vertex array glEnableClientState(GL_TEXTURE_COORD_ARRAY); // Enable texture coords array glEnableClientState(GL_NORMAL_ARRAY); // Enable normals array - + glVertexPointer(3, GL_FLOAT, 0, model.mesh.vertices); // Pointer to vertex coords array glTexCoordPointer(2, GL_FLOAT, 0, model.mesh.texcoords); // Pointer to texture coords array glNormalPointer(GL_FLOAT, 0, model.mesh.normals); // Pointer to normals array //glColorPointer(4, GL_UNSIGNED_BYTE, 0, model.mesh.colors); // Pointer to colors array (NOT USED) - + //TraceLog(DEBUG, "Drawing model.mesh, VertexCount: %i", model.mesh.vertexCount); - + rlPushMatrix(); rlTranslatef(position.x, position.y, position.z); rlScalef(scale.x, scale.y, scale.z); //rlRotatef(rotation, 0, 1, 0); - + // TODO: If rotate in multiple axis, get rotation matrix and use rlMultMatrix() rlColor4ub(color.r, color.g, color.b, color.a); glDrawArrays(GL_TRIANGLES, 0, model.mesh.vertexCount); rlPopMatrix(); - + glDisableClientState(GL_VERTEX_ARRAY); // Disable vertex array glDisableClientState(GL_TEXTURE_COORD_ARRAY); // Disable texture coords array glDisableClientState(GL_NORMAL_ARRAY); // Disable normals array - + glDisable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, 0); #endif #if defined(USE_OPENGL_33) || defined(USE_OPENGL_ES2) glUseProgram(shaderProgram); // Use our shader - + // Get transform matrix (rotation -> scale -> translation) Matrix transform = MatrixTransform(position, rotation, scale); Matrix modelviewworld = MatrixMultiply(transform, modelview); - + // NOTE: Drawing in OpenGL 3.3+, transform is passed to shader glUniformMatrix4fv(projectionMatrixLoc, 1, false, GetMatrixVector(projection)); glUniformMatrix4fv(modelviewMatrixLoc, 1, false, GetMatrixVector(modelviewworld)); glUniform1i(textureLoc, 0); // Apply color tinting to model: 2 OPTIONS -/* +/* // OPTION 1 // Update colors array (model.mesh.colors) with color int j = 0; @@ -962,21 +962,21 @@ void rlglDrawModel(Model model, Vector3 position, Vector3 rotation, Vector3 scal model.mesh.colors[j+3] = color.a; j += 4; } - + // Update colors buffer in CPU (using Shader) glBindVertexArray(model.vaoId); GLuint colorVboId; glGetVertexAttribIuiv(2, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &colorVboId); // NOTE: Color VBO is buffer index 2 glBindBuffer(GL_ARRAY_BUFFER, colorVboId); glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(unsigned char)*4*model.mesh.vertexCount, model.mesh.colors); - + // OPTION 2: Just update one uniform on fragment shader // NOTE: It requires shader modification to add uniform (fragment shader) and create location point //glUniform4f(fragmentUniformColorLoc, (float)color.r/255, (float)color.g/255, (float)color.b/255, (float)color.a/255); -*/ - +*/ + //TraceLog(DEBUG, "ShaderProgram: %i, VAO ID: %i, VertexCount: %i", shaderProgram, model.vaoId, model.mesh.vertexCount); - + glBindVertexArray(model.vaoId); glBindTexture(GL_TEXTURE_2D, model.textureId); @@ -997,37 +997,37 @@ void rlglInitGraphicsDevice(int fbWidth, int fbHeight) // NOTE: Don't confuse glViewport with the transformation matrix // NOTE: glViewport just defines the area of the context that you will actually draw to. - + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear used buffers, depth buffer is used for 3D glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set background color (black) //glClearDepth(1.0f); // Clear depth buffer (default) - + glEnable(GL_DEPTH_TEST); // Enables depth testing (required for 3D) glDepthFunc(GL_LEQUAL); // Type of depth testing to apply - + glEnable(GL_BLEND); // Enable color blending (required to work with transparencies) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Color blending function (how colors are mixed) -#ifdef USE_OPENGL_11 +#ifdef USE_OPENGL_11 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Improve quality of color and texture coordinate interpolation (Deprecated in OGL 3.0) // Other options: GL_FASTEST, GL_DONT_CARE (default) #endif - + rlMatrixMode(RL_PROJECTION); // Switch to PROJECTION matrix rlLoadIdentity(); // Reset current matrix (PROJECTION) - + rlOrtho(0, fbWidth, fbHeight, 0, 0, 1); // Config orthographic mode: top-left corner --> (0,0) - + rlMatrixMode(RL_MODELVIEW); // Switch back to MODELVIEW matrix rlLoadIdentity(); // Reset current matrix (MODELVIEW) - + // NOTE: All shapes/models triangles are drawn CCW glEnable(GL_CULL_FACE); // Enable backface culling (Disabled by default) //glCullFace(GL_BACK); // Cull the Back face (default) //glFrontFace(GL_CCW); // Front face are defined counter clockwise (default) -#ifdef USE_OPENGL_11 +#ifdef USE_OPENGL_11 glShadeModel(GL_SMOOTH); // Smooth shading between vertex (vertex colors interpolation) (Deprecated on OpenGL 3.3+) // Possible options: GL_SMOOTH (Color interpolation) or GL_FLAT (no interpolation) #endif @@ -1042,26 +1042,26 @@ unsigned int rlglLoadTexture(unsigned char *data, int width, int height, bool ge GLuint id; glGenTextures(1, &id); // Generate Pointer to the texture - + //glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, id); - + // NOTE: glTexParameteri does NOT affect texture uploading, just the way it's used! glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // Set texture to repead on x-axis glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // Set texture to repead on y-axis bool texIsPOT = false; - + // Check if width and height are power-of-two (POT) if (((width > 0) && ((width & (width - 1)) == 0)) && ((height > 0) && ((height & (height - 1)) == 0))) texIsPOT = true; - + if (genMipmaps && !texIsPOT) { TraceLog(WARNING, "[ID %i] Texture is not power-of-two, mipmaps can not be generated", id); - + genMipmaps = false; } - + // If mipmaps are being used, we configure mag-min filters accordingly if (genMipmaps) { @@ -1072,7 +1072,7 @@ unsigned int rlglLoadTexture(unsigned char *data, int width, int height, bool ge else { // Not using mipmappings - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // Filter for pixel-perfect drawing, alternative: GL_LINEAR + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // Filter for pixel-perfect drawing, alternative: GL_LINEAR glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // Filter for pixel-perfect drawing, alternative: GL_LINEAR } @@ -1087,18 +1087,18 @@ unsigned int rlglLoadTexture(unsigned char *data, int width, int height, bool ge int offset = 0; int size = 0; - + int mipWidth = width; int mipHeight = height; - - // Load the mipmaps + + // Load the mipmaps for (int level = 0; level < mipmapCount; level++) { glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA8, mipWidth, mipHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, data + offset); - + size = mipWidth*mipHeight*4; offset += size; - + mipWidth /= 2; mipHeight /= 2; } @@ -1110,22 +1110,22 @@ unsigned int rlglLoadTexture(unsigned char *data, int width, int height, bool ge #if defined(USE_OPENGL_33) || defined(USE_OPENGL_ES2) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); - + if (genMipmaps) { glGenerateMipmap(GL_TEXTURE_2D); // Generate mipmaps automatically TraceLog(INFO, "[ID %i] Mipmaps generated automatically for new texture", id); } - + #endif // At this point we have the image converted to texture and uploaded to GPU - + // Unbind current texture glBindTexture(GL_TEXTURE_2D, 0); - + TraceLog(INFO, "[ID %i] New texture created (%i x %i)", id, width, height); - + return id; } @@ -1138,14 +1138,14 @@ unsigned int rlglLoadCompressedTexture(unsigned char *data, int width, int heigh { // Create one OpenGL texture GLuint id; - + glGenTextures(1, &id); - + TraceLog(DEBUG, "Compressed texture width: %i", width); TraceLog(DEBUG, "Compressed texture height: %i", height); TraceLog(DEBUG, "Compressed texture mipmap levels: %i", mipmapCount); TraceLog(DEBUG, "Compressed texture format: 0x%x", compFormat); - + if (compFormat == 0) { TraceLog(WARNING, "[ID %i] Texture compressed format not recognized", id); @@ -1156,24 +1156,24 @@ unsigned int rlglLoadCompressedTexture(unsigned char *data, int width, int heigh // Bind the texture glBindTexture(GL_TEXTURE_2D, id); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - + int blockSize = 0; int offset = 0; - + if (compFormat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) blockSize = 8; else blockSize = 16; - - // Load the mipmaps - for (int level = 0; level < mipmapCount && (width || height); level++) - { + + // Load the mipmaps + for (int level = 0; level < mipmapCount && (width || height); level++) + { // NOTE: size specifies the number of bytes of image data (S3TC/DXTC) unsigned int size = ((width + 3)/4)*((height + 3)/4)*blockSize; - - glCompressedTexImage2D(GL_TEXTURE_2D, level, compFormat, width, height, 0, size, data + offset); - + + glCompressedTexImage2D(GL_TEXTURE_2D, level, compFormat, width, height, 0, size, data + offset); + offset += size; - width /= 2; - height /= 2; + width /= 2; + height /= 2; // Security check for NPOT textures if (width < 1) width = 1; @@ -1193,37 +1193,37 @@ unsigned int rlglLoadModel(VertexData mesh) // Initialize Quads VAO (Buffer A) glGenVertexArrays(1, &vaoModel); glBindVertexArray(vaoModel); - + // Create buffers for our vertex data (positions, texcoords, normals) glGenBuffers(3, vertexBuffer); - + // Enable vertex attributes: position glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[0]); glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*mesh.vertexCount, mesh.vertices, GL_STATIC_DRAW); glEnableVertexAttribArray(vertexLoc); glVertexAttribPointer(vertexLoc, 3, GL_FLOAT, 0, 0, 0); - + // Enable vertex attributes: texcoords glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[1]); - glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*mesh.vertexCount, mesh.texcoords, GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*mesh.vertexCount, mesh.texcoords, GL_STATIC_DRAW); glEnableVertexAttribArray(texcoordLoc); glVertexAttribPointer(texcoordLoc, 2, GL_FLOAT, 0, 0, 0); - + // Enable vertex attributes: normals //glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[2]); - //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*mesh.vertexCount, mesh.normals, GL_STATIC_DRAW); + //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*mesh.vertexCount, mesh.normals, GL_STATIC_DRAW); //glEnableVertexAttribArray(normalLoc); //glVertexAttribPointer(normalLoc, 3, GL_FLOAT, 0, 0, 0); - + // Enable vertex attributes: colors glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[2]); - glBufferData(GL_ARRAY_BUFFER, sizeof(unsigned char)*4*mesh.vertexCount, mesh.colors, GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, sizeof(unsigned char)*4*mesh.vertexCount, mesh.colors, GL_STATIC_DRAW); glEnableVertexAttribArray(colorLoc); glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); - + if (vaoModel > 0) TraceLog(INFO, "[ID %i] Model uploaded successfully to VRAM (GPU)", vaoModel); else TraceLog(WARNING, "Model could not be uploaded to VRAM (GPU)"); - + return vaoModel; } #endif @@ -1235,10 +1235,10 @@ unsigned char *rlglReadScreenPixels(int width, int height) // NOTE: glReadPixels returns image flipped vertically -> (0,0) is the bottom left corner of the framebuffer glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, screenData); - + // Flip image vertically! unsigned char *imgData = (unsigned char *)malloc(width * height * sizeof(unsigned char) * 4); - + for (int y = height-1; y >= 0; y--) { for (int x = 0; x < (width*4); x++) @@ -1246,9 +1246,9 @@ unsigned char *rlglReadScreenPixels(int width, int height) imgData[x + (height - y - 1)*width*4] = screenData[x + (y*width*4)]; } } - + free(screenData); - + return imgData; // NOTE: image data should be freed } @@ -1275,7 +1275,7 @@ void PrintModelviewMatrix() // Load Shaders (Vertex and Fragment) static GLuint LoadDefaultShaders() { - // NOTE: Shaders are written using GLSL 110 (desktop), that is equivalent to GLSL 100 on ES2 + // NOTE: Shaders are written using GLSL 110 (desktop), that is equivalent to GLSL 100 on ES2 // Vertex shader directly defined, no external file required char vShaderStr[] = " #version 110 \n" // Equivalent to version 100 on ES2 @@ -1292,7 +1292,7 @@ static GLuint LoadDefaultShaders() " fragColor = vertexColor; \n" " gl_Position = projectionMatrix * modelviewMatrix * vec4(vertexPosition, 1.0); \n" "} \n"; - + // Fragment shader directly defined, no external file required char fShaderStr[] = " #version 110 \n" // Equivalent to version 100 on ES2 "uniform sampler2D texture0; \n" @@ -1306,34 +1306,34 @@ static GLuint LoadDefaultShaders() GLuint program; GLuint vertexShader; GLuint fragmentShader; - + vertexShader = glCreateShader(GL_VERTEX_SHADER); fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); - + const char *pvs = vShaderStr; const char *pfs = fShaderStr; - + glShaderSource(vertexShader, 1, &pvs, NULL); glShaderSource(fragmentShader, 1, &pfs, NULL); glCompileShader(vertexShader); glCompileShader(fragmentShader); - + TraceLog(INFO, "[ID %i] Default vertex shader compiled successfully", vertexShader); TraceLog(INFO, "[ID %i] Default fragment shader compiled successfully", fragmentShader); - + program = glCreateProgram(); - + glAttachShader(program, vertexShader); glAttachShader(program, fragmentShader); - + glLinkProgram(program); - + glDeleteShader(vertexShader); glDeleteShader(fragmentShader); - + TraceLog(INFO, "[ID %i] Default shader program loaded successfully", program); - + return program; } @@ -1348,62 +1348,62 @@ static GLuint LoadShaders(char *vertexFileName, char *fragmentFileName) GLuint program; GLuint vertexShader; GLuint fragmentShader; - + vertexShader = glCreateShader(GL_VERTEX_SHADER); fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); - + const char *pvs = vShaderStr; const char *pfs = fShaderStr; - + glShaderSource(vertexShader, 1, &pvs, NULL); glShaderSource(fragmentShader, 1, &pfs, NULL); glCompileShader(vertexShader); glCompileShader(fragmentShader); - + TraceLog(INFO, "[ID %i] Vertex shader compiled successfully", vertexShader); TraceLog(INFO, "[ID %i] Fragment shader compiled successfully", fragmentShader); - + program = glCreateProgram(); - + glAttachShader(program, vertexShader); glAttachShader(program, fragmentShader); - + glLinkProgram(program); - + glDeleteShader(vertexShader); glDeleteShader(fragmentShader); - + TraceLog(INFO, "[ID %i] Shader program loaded successfully", program); - + return program; } // Read shader text file -static char *TextFileRead(char *fn) +static char *TextFileRead(char *fn) { FILE *fp; char *text = NULL; int count=0; - if (fn != NULL) + if (fn != NULL) { fp = fopen(fn,"rt"); - if (fp != NULL) + if (fp != NULL) { fseek(fp, 0, SEEK_END); count = ftell(fp); rewind(fp); - if (count > 0) + if (count > 0) { text = (char *)malloc(sizeof(char) * (count+1)); count = fread(text, sizeof(char), count, fp); text[count] = '\0'; } - + fclose(fp); } } @@ -1419,32 +1419,32 @@ static void InitializeBuffers() for (int i = 0; i < (3*2*MAX_LINES_BATCH); i++) lines.vertices[i] = 0.0; for (int i = 0; i < (4*2*MAX_LINES_BATCH); i++) lines.colors[i] = 0; - + lines.vCounter = 0; lines.cCounter = 0; - + // Initialize triangles arrays (vertex position and color data) triangles.vertices = (float *)malloc(sizeof(float)*3*3*MAX_TRIANGLES_BATCH); // 3 float by vertex, 3 vertex by triangle triangles.colors = (unsigned char *)malloc(sizeof(unsigned char)*4*3*MAX_TRIANGLES_BATCH); // 4 float by color, 3 colors by triangle for (int i = 0; i < (3*3*MAX_TRIANGLES_BATCH); i++) triangles.vertices[i] = 0.0; for (int i = 0; i < (4*3*MAX_TRIANGLES_BATCH); i++) triangles.colors[i] = 0; - + triangles.vCounter = 0; triangles.cCounter = 0; - + // Initialize quads arrays (vertex position, texcoord and color data... and indexes) quads.vertices = (float *)malloc(sizeof(float)*3*4*MAX_QUADS_BATCH); // 3 float by vertex, 4 vertex by quad quads.texcoords = (float *)malloc(sizeof(float)*2*4*MAX_QUADS_BATCH); // 2 float by texcoord, 4 texcoord by quad quads.colors = (unsigned char *)malloc(sizeof(unsigned char)*4*4*MAX_QUADS_BATCH); // 4 float by color, 4 colors by quad quads.indices = (unsigned int *)malloc(sizeof(int)*6*MAX_QUADS_BATCH); // 6 int by quad (indices) - + for (int i = 0; i < (3*4*MAX_QUADS_BATCH); i++) quads.vertices[i] = 0.0; for (int i = 0; i < (2*4*MAX_QUADS_BATCH); i++) quads.texcoords[i] = 0.0; for (int i = 0; i < (4*4*MAX_QUADS_BATCH); i++) quads.colors[i] = 0; - + int k = 0; - + // Indices can be initialized right now for (int i = 0; i < (6*MAX_QUADS_BATCH); i+=6) { @@ -1454,10 +1454,10 @@ static void InitializeBuffers() quads.indices[i+3] = 4*k; quads.indices[i+4] = 4*k+2; quads.indices[i+5] = 4*k+3; - + k++; } - + quads.vCounter = 0; quads.tcCounter = 0; quads.cCounter = 0; @@ -1469,75 +1469,75 @@ static void InitializeVAOs() // Initialize Lines VAO glGenVertexArrays(1, &vaoLines); glBindVertexArray(vaoLines); - + // Create buffers for our vertex data glGenBuffers(2, linesBuffer); - + // Lines - Vertex positions buffer binding and attributes enable glBindBuffer(GL_ARRAY_BUFFER, linesBuffer[0]); glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*2*MAX_LINES_BATCH, lines.vertices, GL_DYNAMIC_DRAW); glEnableVertexAttribArray(vertexLoc); glVertexAttribPointer(vertexLoc, 3, GL_FLOAT, 0, 0, 0); - + // Lines - colors buffer glBindBuffer(GL_ARRAY_BUFFER, linesBuffer[1]); glBufferData(GL_ARRAY_BUFFER, sizeof(unsigned char)*4*2*MAX_LINES_BATCH, lines.colors, GL_DYNAMIC_DRAW); glEnableVertexAttribArray(colorLoc); glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); - + TraceLog(INFO, "[ID %i] Lines VAO initialized successfully", vaoLines); - //-------------------------------------------------------------- - + //-------------------------------------------------------------- + // Initialize Triangles VAO glGenVertexArrays(1, &vaoTriangles); glBindVertexArray(vaoTriangles); - + // Create buffers for our vertex data glGenBuffers(2, trianglesBuffer); - + // Enable vertex attributes glBindBuffer(GL_ARRAY_BUFFER, trianglesBuffer[0]); glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*3*MAX_TRIANGLES_BATCH, triangles.vertices, GL_DYNAMIC_DRAW); glEnableVertexAttribArray(vertexLoc); glVertexAttribPointer(vertexLoc, 3, GL_FLOAT, 0, 0, 0); - + glBindBuffer(GL_ARRAY_BUFFER, trianglesBuffer[1]); glBufferData(GL_ARRAY_BUFFER, sizeof(unsigned char)*4*3*MAX_TRIANGLES_BATCH, triangles.colors, GL_DYNAMIC_DRAW); glEnableVertexAttribArray(colorLoc); glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); - + TraceLog(INFO, "[ID %i] Triangles VAO initialized successfully", vaoTriangles); - //-------------------------------------------------------------- - + //-------------------------------------------------------------- + // Initialize Quads VAO (Buffer A) glGenVertexArrays(1, &vaoQuads); glBindVertexArray(vaoQuads); - + // Create buffers for our vertex data glGenBuffers(4, quadsBuffer); - + // Enable vertex attributes glBindBuffer(GL_ARRAY_BUFFER, quadsBuffer[0]); glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*4*MAX_QUADS_BATCH, quads.vertices, GL_DYNAMIC_DRAW); glEnableVertexAttribArray(vertexLoc); glVertexAttribPointer(vertexLoc, 3, GL_FLOAT, 0, 0, 0); - + glBindBuffer(GL_ARRAY_BUFFER, quadsBuffer[1]); - glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*4*MAX_QUADS_BATCH, quads.texcoords, GL_DYNAMIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*4*MAX_QUADS_BATCH, quads.texcoords, GL_DYNAMIC_DRAW); glEnableVertexAttribArray(texcoordLoc); glVertexAttribPointer(texcoordLoc, 2, GL_FLOAT, 0, 0, 0); - + glBindBuffer(GL_ARRAY_BUFFER, quadsBuffer[2]); - glBufferData(GL_ARRAY_BUFFER, sizeof(unsigned char)*4*4*MAX_QUADS_BATCH, quads.colors, GL_DYNAMIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, sizeof(unsigned char)*4*4*MAX_QUADS_BATCH, quads.colors, GL_DYNAMIC_DRAW); glEnableVertexAttribArray(colorLoc); glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); - + // Fill index buffer glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quadsBuffer[3]); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int)*6*MAX_QUADS_BATCH, quads.indices, GL_STATIC_DRAW); - + TraceLog(INFO, "[ID %i] Quads VAO initialized successfully", vaoQuads); - + // Unbind the current VAO glBindVertexArray(0); } @@ -1547,37 +1547,37 @@ static void UpdateBuffers() { // Activate Lines VAO glBindVertexArray(vaoLines); - + // Lines - vertex positions buffer glBindBuffer(GL_ARRAY_BUFFER, linesBuffer[0]); //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*2*MAX_LINES_BATCH, lines.vertices, GL_DYNAMIC_DRAW); glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*3*lines.vCounter, lines.vertices); // target - offset (in bytes) - size (in bytes) - data pointer - + // Lines - colors buffer glBindBuffer(GL_ARRAY_BUFFER, linesBuffer[1]); //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*2*MAX_LINES_BATCH, lines.colors, GL_DYNAMIC_DRAW); glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(unsigned char)*4*lines.cCounter, lines.colors); - - //-------------------------------------------------------------- - + + //-------------------------------------------------------------- + // Activate Triangles VAO glBindVertexArray(vaoTriangles); - + // Triangles - vertex positions buffer glBindBuffer(GL_ARRAY_BUFFER, trianglesBuffer[0]); //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*3*MAX_TRIANGLES_BATCH, triangles.vertices, GL_DYNAMIC_DRAW); glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*3*triangles.vCounter, triangles.vertices); - + // Triangles - colors buffer glBindBuffer(GL_ARRAY_BUFFER, trianglesBuffer[1]); //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*3*MAX_TRIANGLES_BATCH, triangles.colors, GL_DYNAMIC_DRAW); glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(unsigned char)*4*triangles.cCounter, triangles.colors); - + //-------------------------------------------------------------- // Activate Quads VAO glBindVertexArray(vaoQuads); - + // Quads - vertex positions buffer glBindBuffer(GL_ARRAY_BUFFER, quadsBuffer[0]); //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*4*MAX_QUADS_BATCH, quads.vertices, GL_DYNAMIC_DRAW); @@ -1587,19 +1587,19 @@ static void UpdateBuffers() glBindBuffer(GL_ARRAY_BUFFER, quadsBuffer[1]); //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*4*MAX_QUADS_BATCH, quads.texcoords, GL_DYNAMIC_DRAW); glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*2*quads.vCounter, quads.texcoords); - + // Quads - colors buffer glBindBuffer(GL_ARRAY_BUFFER, quadsBuffer[2]); //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*4*MAX_QUADS_BATCH, quads.colors, GL_DYNAMIC_DRAW); glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(unsigned char)*4*quads.vCounter, quads.colors); - + // Another option would be using buffer mapping... //triangles.vertices = glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE); // Now we can modify vertices //glUnmapBuffer(GL_ARRAY_BUFFER); - + //-------------------------------------------------------------- - + // Unbind the current VAO glBindVertexArray(0); } @@ -1621,26 +1621,26 @@ static int GenerateMipmaps(unsigned char *data, int baseWidth, int baseHeight) { if (width != 1) width /= 2; if (height != 1) height /= 2; - + TraceLog(DEBUG, "Next mipmap size: %i x %i", width, height); - + mipmapCount++; - + size += (width*height*4); // Add mipmap size (in bytes) } - + TraceLog(DEBUG, "Total mipmaps required: %i", mipmapCount); TraceLog(DEBUG, "Total size of data required: %i", size); - + unsigned char *temp = realloc(data, size); - + if (temp != NULL) data = temp; else TraceLog(WARNING, "Mipmaps required memory could not be allocated"); - + width = baseWidth; height = baseHeight; size = (width*height*4); - + // Generate mipmaps // NOTE: Every mipmap data is stored after data pixel *image = (pixel *)malloc(width*height*sizeof(pixel)); @@ -1656,16 +1656,16 @@ static int GenerateMipmaps(unsigned char *data, int baseWidth, int baseHeight) image[j].a = data[i + 3]; j++; } - + TraceLog(DEBUG, "Mipmap base (%i, %i)", width, height); - + for (int mip = 1; mip < mipmapCount; mip++) { mipmap = GenNextMipmap(image, width, height); - + offset += (width*height*4); // Size of last mipmap j = 0; - + width /= 2; height /= 2; size = (width*height*4); // Mipmap size to store after offset @@ -1676,18 +1676,18 @@ static int GenerateMipmaps(unsigned char *data, int baseWidth, int baseHeight) data[offset + i] = mipmap[j].r; data[offset + i + 1] = mipmap[j].g; data[offset + i + 2] = mipmap[j].b; - data[offset + i + 3] = mipmap[j].a; + data[offset + i + 3] = mipmap[j].a; j++; } free(image); - + image = mipmap; mipmap = NULL; } - + free(mipmap); // free mipmap data - + return mipmapCount; } @@ -1703,11 +1703,11 @@ static pixel *GenNextMipmap(pixel *srcData, int srcWidth, int srcHeight) pixel *mipmap = (pixel *)malloc(width*height*sizeof(pixel)); // Scaling algorithm works perfectly (box-filter) - for (int y = 0; y < height; y++) + for (int y = 0; y < height; y++) { y2 = 2 * y; - for (int x = 0; x < width; x++) + for (int x = 0; x < width; x++) { x2 = 2 * x; @@ -1727,7 +1727,7 @@ static pixel *GenNextMipmap(pixel *srcData, int srcWidth, int srcHeight) mipmap[y*width + x].a = (prow.a + pcol.a)/2; } } - + TraceLog(DEBUG, "Mipmap generated successfully (%i, %i)", width, height); return mipmap; @@ -1745,7 +1745,7 @@ void TraceLog(int msgType, const char *text, ...) { va_list args; va_start(args, text); - + switch(msgType) { case INFO: fprintf(stdout, "INFO: "); break; @@ -1754,12 +1754,12 @@ void TraceLog(int msgType, const char *text, ...) case DEBUG: fprintf(stdout, "DEBUG: "); break; default: break; } - + vfprintf(stdout, text, args); fprintf(stdout, "\n"); - + va_end(args); - + if (msgType == ERROR) exit(1); } #endif \ No newline at end of file diff --git a/src/rlgl.h b/src/rlgl.h index ee5f742c..1210c831 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -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 diff --git a/src/shapes.c b/src/shapes.c index 7d4c0d04..17210f21 100644 --- a/src/shapes.c +++ b/src/shapes.c @@ -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 // Required for abs() function #include // 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; -} +} diff --git a/src/text.c b/src/text.c index c8b9f81d..a1473b3e 100644 --- a/src/text.c +++ b/src/text.c @@ -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; } \ No newline at end of file diff --git a/src/textures.c b/src/textures.c index 2bbf8e61..39947d12 100644 --- a/src/textures.c +++ b/src/textures.c @@ -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; } \ No newline at end of file diff --git a/src/utils.c b/src/utils.c index 3768212e..254cc955 100644 --- a/src/utils.c +++ b/src/utils.c @@ -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 ""; diff --git a/src/utils.h b/src/utils.h index ed10c3c7..ac8d55b1 100644 --- a/src/utils.h +++ b/src/utils.h @@ -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