Merge pull request #2 from raysan5/testing
Integrate raylib 1.1 changes into master
This commit is contained in:
commit
650a8f7f15
25 changed files with 25258 additions and 1886 deletions
73
external/glew/LICENSE.txt
vendored
Normal file
73
external/glew/LICENSE.txt
vendored
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
The OpenGL Extension Wrangler Library
|
||||||
|
Copyright (C) 2002-2007, Milan Ikits <milan ikits[]ieee org>
|
||||||
|
Copyright (C) 2002-2007, Marcelo E. Magallon <mmagallo[]debian org>
|
||||||
|
Copyright (C) 2002, Lev Povalahev
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
* The name of the author may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
|
||||||
|
Mesa 3-D graphics library
|
||||||
|
Version: 7.0
|
||||||
|
|
||||||
|
Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included
|
||||||
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||||
|
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
|
||||||
|
Copyright (c) 2007 The Khronos Group Inc.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and/or associated documentation files (the
|
||||||
|
"Materials"), to deal in the Materials without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Materials, and to
|
||||||
|
permit persons to whom the Materials are furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included
|
||||||
|
in all copies or substantial portions of the Materials.
|
||||||
|
|
||||||
|
THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
BIN
external/glew/glew32.dll
vendored
Normal file
BIN
external/glew/glew32.dll
vendored
Normal file
Binary file not shown.
18062
external/glew/include/GL/glew.h
vendored
Normal file
18062
external/glew/include/GL/glew.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
1669
external/glew/include/GL/glxew.h
vendored
Normal file
1669
external/glew/include/GL/glxew.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
1421
external/glew/include/GL/wglew.h
vendored
Normal file
1421
external/glew/include/GL/wglew.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
BIN
external/glew/lib/libglew32.a
vendored
Normal file
BIN
external/glew/lib/libglew32.a
vendored
Normal file
Binary file not shown.
BIN
external/glew/lib/libglew32.dll.a
vendored
Normal file
BIN
external/glew/lib/libglew32.dll.a
vendored
Normal file
Binary file not shown.
615
src/audio.c
615
src/audio.c
|
@ -37,7 +37,7 @@
|
||||||
|
|
||||||
#include "utils.h" // rRES data decompression utility function
|
#include "utils.h" // rRES data decompression utility function
|
||||||
|
|
||||||
//#include "stb_vorbis.h" // TODO: OGG loading functions
|
//#include "stb_vorbis.h" // OGG loading functions
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Defines and Macros
|
// Defines and Macros
|
||||||
|
@ -47,6 +47,29 @@
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Types and Structures Definition
|
// Types and Structures Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
// Sound source type (all file loaded in memory)
|
||||||
|
/*
|
||||||
|
struct Sound {
|
||||||
|
unsigned int source;
|
||||||
|
unsigned int buffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Music type (file streamming from memory)
|
||||||
|
// NOTE: Anything longer than ~10 seconds should be Music...
|
||||||
|
struct Music {
|
||||||
|
stb_vorbis* stream;
|
||||||
|
stb_vorbis_info info;
|
||||||
|
|
||||||
|
ALuint id;
|
||||||
|
ALuint buffers[2];
|
||||||
|
ALuint source;
|
||||||
|
ALenum format;
|
||||||
|
|
||||||
|
int bufferSize;
|
||||||
|
int totalSamplesLeft;
|
||||||
|
bool loop;
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
// Wave file data
|
// Wave file data
|
||||||
typedef struct Wave {
|
typedef struct Wave {
|
||||||
|
@ -60,7 +83,8 @@ typedef struct Wave {
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Global Variables Definition
|
// Global Variables Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Nop...
|
static bool musicIsPlaying;
|
||||||
|
static Music *currentMusic;
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module specific Functions Declaration
|
// Module specific Functions Declaration
|
||||||
|
@ -68,6 +92,10 @@ typedef struct Wave {
|
||||||
static Wave LoadWAV(char *fileName);
|
static Wave LoadWAV(char *fileName);
|
||||||
static void UnloadWAV(Wave wave);
|
static void UnloadWAV(Wave wave);
|
||||||
//static Ogg LoadOGG(char *fileName);
|
//static Ogg LoadOGG(char *fileName);
|
||||||
|
static bool MusicStream(Music music, ALuint buffer);
|
||||||
|
|
||||||
|
extern bool MusicStreamUpdate();
|
||||||
|
extern void PlayCurrentMusic();
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module Functions Definition - Window and OpenGL Context Functions
|
// Module Functions Definition - Window and OpenGL Context Functions
|
||||||
|
@ -79,30 +107,27 @@ void InitAudioDevice()
|
||||||
// Open and initialize a device with default settings
|
// Open and initialize a device with default settings
|
||||||
ALCdevice *device = alcOpenDevice(NULL);
|
ALCdevice *device = alcOpenDevice(NULL);
|
||||||
|
|
||||||
if(!device)
|
if(!device) TraceLog(ERROR, "Could not open audio device");
|
||||||
{
|
|
||||||
fprintf(stderr, "Could not open a device!\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
ALCcontext *context = alcCreateContext(device, NULL);
|
ALCcontext *context = alcCreateContext(device, NULL);
|
||||||
|
|
||||||
if(context == NULL || alcMakeContextCurrent(context) == ALC_FALSE)
|
if(context == NULL || alcMakeContextCurrent(context) == ALC_FALSE)
|
||||||
{
|
{
|
||||||
if(context != NULL) alcDestroyContext(context);
|
if(context != NULL) alcDestroyContext(context);
|
||||||
|
|
||||||
alcCloseDevice(device);
|
alcCloseDevice(device);
|
||||||
|
|
||||||
fprintf(stderr, "Could not set a context!\n");
|
TraceLog(ERROR, "Could not setup audio context");
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Opened \"%s\"\n", alcGetString(device, ALC_DEVICE_SPECIFIER));
|
TraceLog(INFO, "Audio device and context initialized: %s\n", alcGetString(device, ALC_DEVICE_SPECIFIER));
|
||||||
|
|
||||||
// Listener definition (just for 2D)
|
// Listener definition (just for 2D)
|
||||||
alListener3f(AL_POSITION, 0, 0, 0);
|
alListener3f(AL_POSITION, 0, 0, 0);
|
||||||
alListener3f(AL_VELOCITY, 0, 0, 0);
|
alListener3f(AL_VELOCITY, 0, 0, 0);
|
||||||
alListener3f(AL_ORIENTATION, 0, 0, -1);
|
alListener3f(AL_ORIENTATION, 0, 0, -1);
|
||||||
|
|
||||||
|
musicIsPlaying = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close the audio device for the current context, and destroys the context
|
// Close the audio device for the current context, and destroys the context
|
||||||
|
@ -111,7 +136,7 @@ void CloseAudioDevice()
|
||||||
ALCdevice *device;
|
ALCdevice *device;
|
||||||
ALCcontext *context = alcGetCurrentContext();
|
ALCcontext *context = alcGetCurrentContext();
|
||||||
|
|
||||||
if (context == NULL) return;
|
if (context == NULL) TraceLog(WARNING, "Could not get current audio context for closing");
|
||||||
|
|
||||||
device = alcGetContextsDevice(context);
|
device = alcGetContextsDevice(context);
|
||||||
|
|
||||||
|
@ -131,7 +156,7 @@ Sound LoadSound(char *fileName)
|
||||||
// NOTE: Buffer space is allocated inside LoadWAV, Wave must be freed
|
// NOTE: Buffer space is allocated inside LoadWAV, Wave must be freed
|
||||||
Wave wave = LoadWAV(fileName);
|
Wave wave = LoadWAV(fileName);
|
||||||
|
|
||||||
ALenum format;
|
ALenum format = 0;
|
||||||
// The OpenAL format is worked out by looking at the number of channels and the bits per sample
|
// 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)
|
||||||
{
|
{
|
||||||
|
@ -169,10 +194,8 @@ Sound LoadSound(char *fileName)
|
||||||
// Unallocate WAV data
|
// Unallocate WAV data
|
||||||
UnloadWAV(wave);
|
UnloadWAV(wave);
|
||||||
|
|
||||||
printf("Sample rate: %i\n", wave.sampleRate);
|
TraceLog(INFO, "[%s] Sound file loaded successfully", fileName);
|
||||||
printf("Channels: %i\n", wave.channels);
|
TraceLog(INFO, "[%s] Sample rate: %i - Channels: %i", fileName, wave.sampleRate, wave.channels);
|
||||||
|
|
||||||
printf("Audio file loaded...!\n");
|
|
||||||
|
|
||||||
sound.source = source;
|
sound.source = source;
|
||||||
sound.buffer = buffer;
|
sound.buffer = buffer;
|
||||||
|
@ -196,139 +219,136 @@ Sound LoadSoundFromRES(const char *rresName, int resId)
|
||||||
|
|
||||||
FILE *rresFile = fopen(rresName, "rb");
|
FILE *rresFile = fopen(rresName, "rb");
|
||||||
|
|
||||||
if (!rresFile) printf("Error opening raylib Resource file\n");
|
if (!rresFile) TraceLog(WARNING, "[%s] Could not open raylib resource file", rresName);
|
||||||
|
else
|
||||||
// Read rres file (basic file check - id)
|
|
||||||
fread(&id[0], sizeof(char), 1, rresFile);
|
|
||||||
fread(&id[1], sizeof(char), 1, rresFile);
|
|
||||||
fread(&id[2], sizeof(char), 1, rresFile);
|
|
||||||
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'))
|
|
||||||
{
|
{
|
||||||
printf("This is not a valid raylib Resource file!\n");
|
// Read rres file (basic file check - id)
|
||||||
exit(1);
|
fread(&id[0], sizeof(char), 1, rresFile);
|
||||||
}
|
fread(&id[1], sizeof(char), 1, rresFile);
|
||||||
|
fread(&id[2], sizeof(char), 1, rresFile);
|
||||||
// Read number of resources embedded
|
fread(&id[3], sizeof(char), 1, rresFile);
|
||||||
fread(&numRes, sizeof(short), 1, rresFile);
|
fread(&version, sizeof(char), 1, rresFile);
|
||||||
|
fread(&useless, sizeof(char), 1, rresFile);
|
||||||
for (int i = 0; i < numRes; i++)
|
|
||||||
{
|
|
||||||
fread(&infoHeader, sizeof(ResInfoHeader), 1, rresFile);
|
|
||||||
|
|
||||||
if (infoHeader.id == resId)
|
if ((id[0] != 'r') && (id[1] != 'R') && (id[2] != 'E') &&(id[3] != 'S'))
|
||||||
{
|
{
|
||||||
found = true;
|
TraceLog(WARNING, "[%s] This is not a valid raylib resource file", rresName);
|
||||||
|
|
||||||
// Check data is of valid SOUND type
|
|
||||||
if (infoHeader.type == 1) // SOUND data type
|
|
||||||
{
|
|
||||||
// TODO: Check data compression type
|
|
||||||
// NOTE: We suppose compression type 2 (DEFLATE - default)
|
|
||||||
|
|
||||||
// Reading SOUND parameters
|
|
||||||
Wave wave;
|
|
||||||
short sampleRate, bps;
|
|
||||||
char channels, reserved;
|
|
||||||
|
|
||||||
fread(&sampleRate, sizeof(short), 1, rresFile); // Sample rate (frequency)
|
|
||||||
fread(&bps, sizeof(short), 1, rresFile); // Bits per sample
|
|
||||||
fread(&channels, 1, 1, rresFile); // Channels (1 - mono, 2 - stereo)
|
|
||||||
fread(&reserved, 1, 1, rresFile); // <reserved>
|
|
||||||
|
|
||||||
printf("Sample rate: %i\n", (int)sampleRate);
|
|
||||||
printf("Bits per sample: %i\n", (int)bps);
|
|
||||||
printf("Channels: %i\n", (int)channels);
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
// The OpenAL format is worked out by looking at the number of channels and the bits per sample
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
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_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;
|
|
||||||
alGenBuffers(1, &buffer); // Generate pointer to buffer
|
|
||||||
|
|
||||||
// Upload sound data to buffer
|
|
||||||
alBufferData(buffer, format, (void*)wave.data, wave.dataSize, wave.sampleRate);
|
|
||||||
|
|
||||||
// Attach sound buffer to source
|
|
||||||
alSourcei(source, AL_BUFFER, buffer);
|
|
||||||
|
|
||||||
// Unallocate WAV data
|
|
||||||
UnloadWAV(wave);
|
|
||||||
|
|
||||||
printf("Audio file loaded...!\n");
|
|
||||||
|
|
||||||
sound.source = source;
|
|
||||||
sound.buffer = buffer;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
|
|
||||||
printf("Required resource do not seem to be a valid IMAGE resource\n");
|
|
||||||
exit(2);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Depending on type, skip the right amount of parameters
|
// Read number of resources embedded
|
||||||
switch (infoHeader.type)
|
fread(&numRes, sizeof(short), 1, rresFile);
|
||||||
{
|
|
||||||
case 0: fseek(rresFile, 6, SEEK_CUR); break; // IMAGE: Jump 6 bytes of parameters
|
|
||||||
case 1: fseek(rresFile, 6, SEEK_CUR); break; // SOUND: Jump 6 bytes of parameters
|
|
||||||
case 2: fseek(rresFile, 5, SEEK_CUR); break; // MODEL: Jump 5 bytes of parameters (TODO: Review)
|
|
||||||
case 3: break; // TEXT: No parameters
|
|
||||||
case 4: break; // RAW: No parameters
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Jump DATA to read next infoHeader
|
for (int i = 0; i < numRes; i++)
|
||||||
fseek(rresFile, infoHeader.size, SEEK_CUR);
|
{
|
||||||
}
|
fread(&infoHeader, sizeof(ResInfoHeader), 1, rresFile);
|
||||||
|
|
||||||
|
if (infoHeader.id == resId)
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
|
||||||
|
// Check data is of valid SOUND type
|
||||||
|
if (infoHeader.type == 1) // SOUND data type
|
||||||
|
{
|
||||||
|
// TODO: Check data compression type
|
||||||
|
// NOTE: We suppose compression type 2 (DEFLATE - default)
|
||||||
|
|
||||||
|
// Reading SOUND parameters
|
||||||
|
Wave wave;
|
||||||
|
short sampleRate, bps;
|
||||||
|
char channels, reserved;
|
||||||
|
|
||||||
|
fread(&sampleRate, sizeof(short), 1, rresFile); // Sample rate (frequency)
|
||||||
|
fread(&bps, sizeof(short), 1, rresFile); // Bits per sample
|
||||||
|
fread(&channels, 1, 1, rresFile); // Channels (1 - mono, 2 - stereo)
|
||||||
|
fread(&reserved, 1, 1, rresFile); // <reserved>
|
||||||
|
|
||||||
|
wave.sampleRate = sampleRate;
|
||||||
|
wave.dataSize = infoHeader.srcSize;
|
||||||
|
wave.bitsPerSample = bps;
|
||||||
|
wave.channels = (short)channels;
|
||||||
|
|
||||||
|
unsigned char *data = malloc(infoHeader.size);
|
||||||
|
|
||||||
|
fread(data, infoHeader.size, 1, rresFile);
|
||||||
|
|
||||||
|
wave.data = DecompressData(data, infoHeader.size, infoHeader.srcSize);
|
||||||
|
|
||||||
|
free(data);
|
||||||
|
|
||||||
|
// Convert wave to Sound (OpenAL)
|
||||||
|
ALenum format = 0;
|
||||||
|
|
||||||
|
// The OpenAL format is worked out by looking at the number of channels and the bits per sample
|
||||||
|
if (wave.channels == 1)
|
||||||
|
{
|
||||||
|
if (wave.bitsPerSample == 8 ) format = AL_FORMAT_MONO8;
|
||||||
|
else if (wave.bitsPerSample == 16) format = AL_FORMAT_MONO16;
|
||||||
|
}
|
||||||
|
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_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;
|
||||||
|
alGenBuffers(1, &buffer); // Generate pointer to buffer
|
||||||
|
|
||||||
|
// Upload sound data to buffer
|
||||||
|
alBufferData(buffer, format, (void*)wave.data, wave.dataSize, wave.sampleRate);
|
||||||
|
|
||||||
|
// Attach sound buffer to source
|
||||||
|
alSourcei(source, AL_BUFFER, buffer);
|
||||||
|
|
||||||
|
// Unallocate WAV data
|
||||||
|
UnloadWAV(wave);
|
||||||
|
|
||||||
|
TraceLog(INFO, "[%s] Sound loaded successfully from resource, sample rate: %i", rresName, (int)sampleRate);
|
||||||
|
|
||||||
|
sound.source = source;
|
||||||
|
sound.buffer = buffer;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TraceLog(WARNING, "[%s] Required resource do not seem to be a valid SOUND resource", rresName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Depending on type, skip the right amount of parameters
|
||||||
|
switch (infoHeader.type)
|
||||||
|
{
|
||||||
|
case 0: fseek(rresFile, 6, SEEK_CUR); break; // IMAGE: Jump 6 bytes of parameters
|
||||||
|
case 1: fseek(rresFile, 6, SEEK_CUR); break; // SOUND: Jump 6 bytes of parameters
|
||||||
|
case 2: fseek(rresFile, 5, SEEK_CUR); break; // MODEL: Jump 5 bytes of parameters (TODO: Review)
|
||||||
|
case 3: break; // TEXT: No parameters
|
||||||
|
case 4: break; // RAW: No parameters
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Jump DATA to read next infoHeader
|
||||||
|
fseek(rresFile, infoHeader.size, SEEK_CUR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(rresFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(rresFile);
|
if (!found) TraceLog(WARNING, "[%s] Required resource id [%i] could not be found in the raylib resource file", rresName, resId);
|
||||||
|
|
||||||
if (!found) printf("Required resource id could not be found in the raylib Resource file!\n");
|
|
||||||
|
|
||||||
return sound;
|
return sound;
|
||||||
}
|
}
|
||||||
|
@ -345,7 +365,7 @@ void PlaySound(Sound sound)
|
||||||
{
|
{
|
||||||
alSourcePlay(sound.source); // Play the sound
|
alSourcePlay(sound.source); // Play the sound
|
||||||
|
|
||||||
printf("Playing sound!\n");
|
TraceLog(INFO, "Playing sound");
|
||||||
|
|
||||||
// Find the current position of the sound being played
|
// Find the current position of the sound being played
|
||||||
// NOTE: Only work when the entire file is in a single buffer
|
// NOTE: Only work when the entire file is in a single buffer
|
||||||
|
@ -390,7 +410,7 @@ void StopSound(Sound sound)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if a sound is playing
|
// Check if a sound is playing
|
||||||
bool IsPlaying(Sound sound)
|
bool SoundIsPlaying(Sound sound)
|
||||||
{
|
{
|
||||||
bool playing = false;
|
bool playing = false;
|
||||||
ALint state;
|
ALint state;
|
||||||
|
@ -401,6 +421,16 @@ bool IsPlaying(Sound sound)
|
||||||
return playing;
|
return playing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if music is playing
|
||||||
|
bool MusicIsPlaying(Music music)
|
||||||
|
{
|
||||||
|
ALenum state;
|
||||||
|
|
||||||
|
alGetSourcei(music.source, AL_SOURCE_STATE, &state);
|
||||||
|
|
||||||
|
return (state == AL_PLAYING);
|
||||||
|
}
|
||||||
|
|
||||||
// Set volume for a sound
|
// Set volume for a sound
|
||||||
void SetVolume(Sound sound, float volume)
|
void SetVolume(Sound sound, float volume)
|
||||||
{
|
{
|
||||||
|
@ -450,61 +480,65 @@ static Wave LoadWAV(char *fileName)
|
||||||
|
|
||||||
if (!wavFile)
|
if (!wavFile)
|
||||||
{
|
{
|
||||||
printf("Could not open WAV file.\n");
|
TraceLog(WARNING, "[%s] Could not open WAV file", fileName);
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
// Read in the first chunk into the struct
|
{
|
||||||
fread(&riffHeader, sizeof(RiffHeader), 1, wavFile);
|
// 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' ||
|
// Check for RIFF and WAVE tags
|
||||||
riffHeader.chunkID[1] != 'I' ||
|
if (((riffHeader.chunkID[0] != 'R') || (riffHeader.chunkID[1] != 'I') || (riffHeader.chunkID[2] != 'F') || (riffHeader.chunkID[3] != 'F')) ||
|
||||||
riffHeader.chunkID[2] != 'F' ||
|
((riffHeader.format[0] != 'W') || (riffHeader.format[1] != 'A') || (riffHeader.format[2] != 'V') || (riffHeader.format[3] != 'E')))
|
||||||
riffHeader.chunkID[3] != 'F') ||
|
{
|
||||||
(riffHeader.format[0] != 'W' ||
|
TraceLog(WARNING, "[%s] Invalid RIFF or WAVE Header", fileName);
|
||||||
riffHeader.format[1] != 'A' ||
|
}
|
||||||
riffHeader.format[2] != 'V' ||
|
else
|
||||||
riffHeader.format[3] != 'E'))
|
{
|
||||||
printf("Invalid RIFF or WAVE Header");
|
// Read in the 2nd chunk for the wave info
|
||||||
|
fread(&waveFormat, sizeof(WaveFormat), 1, wavFile);
|
||||||
// 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') ||
|
||||||
// Check for fmt tag
|
(waveFormat.subChunkID[2] != 't') || (waveFormat.subChunkID[3] != ' '))
|
||||||
if (waveFormat.subChunkID[0] != 'f' ||
|
{
|
||||||
waveFormat.subChunkID[1] != 'm' ||
|
TraceLog(WARNING, "[%s] Invalid Wave format", fileName);
|
||||||
waveFormat.subChunkID[2] != 't' ||
|
}
|
||||||
waveFormat.subChunkID[3] != ' ')
|
else
|
||||||
printf("Invalid Wave Format");
|
{
|
||||||
|
// Check for extra parameters;
|
||||||
// Check for extra parameters;
|
if (waveFormat.subChunkSize > 16) fseek(wavFile, sizeof(short), SEEK_CUR);
|
||||||
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);
|
||||||
// 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') ||
|
||||||
// Check for data tag
|
(waveData.subChunkID[2] != 't') || (waveData.subChunkID[3] != 'a'))
|
||||||
if (waveData.subChunkID[0] != 'd' ||
|
{
|
||||||
waveData.subChunkID[1] != 'a' ||
|
TraceLog(WARNING, "[%s] Invalid data header", fileName);
|
||||||
waveData.subChunkID[2] != 't' ||
|
}
|
||||||
waveData.subChunkID[3] != 'a')
|
else
|
||||||
printf("Invalid data header");
|
{
|
||||||
|
// Allocate memory for data
|
||||||
// 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
|
||||||
// Read in the sound data into the soundData variable
|
fread(wave.data, waveData.subChunkSize, 1, wavFile);
|
||||||
fread(wave.data, waveData.subChunkSize, 1, wavFile);
|
|
||||||
|
// Now we set the variables that we need later
|
||||||
// Now we set the variables that we need later
|
wave.dataSize = waveData.subChunkSize;
|
||||||
wave.dataSize = waveData.subChunkSize;
|
wave.sampleRate = waveFormat.sampleRate;
|
||||||
wave.sampleRate = waveFormat.sampleRate;
|
wave.channels = waveFormat.numChannels;
|
||||||
wave.channels = waveFormat.numChannels;
|
wave.bitsPerSample = waveFormat.bitsPerSample;
|
||||||
wave.bitsPerSample = waveFormat.bitsPerSample;
|
|
||||||
|
TraceLog(INFO, "[%s] Wave file loaded successfully", fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fclose(wavFile);
|
fclose(wavFile);
|
||||||
|
}
|
||||||
|
|
||||||
return wave;
|
return wave;
|
||||||
}
|
}
|
||||||
|
@ -516,5 +550,192 @@ static void UnloadWAV(Wave wave)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Ogg data loading
|
// TODO: Ogg data loading
|
||||||
//static Ogg LoadOGG(char *fileName) { }
|
Music LoadMusic(char *fileName)
|
||||||
|
{
|
||||||
|
Music music;
|
||||||
|
|
||||||
|
// Open audio stream
|
||||||
|
music.stream = stb_vorbis_open_filename(fileName, NULL, NULL);
|
||||||
|
|
||||||
|
if (music.stream == NULL) TraceLog(WARNING, "Could not open ogg audio file");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Get file info
|
||||||
|
music.info = stb_vorbis_get_info(music.stream);
|
||||||
|
|
||||||
|
printf("Ogg sample rate: %i\n", music.info.sample_rate);
|
||||||
|
printf("Ogg channels: %i\n", music.info.channels);
|
||||||
|
printf("Temp memory required: %i\n", music.info.temp_memory_required);
|
||||||
|
|
||||||
|
if (music.info.channels == 2) music.format = AL_FORMAT_STEREO16;
|
||||||
|
else music.format = AL_FORMAT_MONO16;
|
||||||
|
|
||||||
|
music.bufferSize = 4096*8;
|
||||||
|
music.loop = true; // We loop by default
|
||||||
|
|
||||||
|
// Create an audio source
|
||||||
|
alGenSources(1, &music.source); // Generate pointer to audio source
|
||||||
|
|
||||||
|
alSourcef(music.source, AL_PITCH, 1);
|
||||||
|
alSourcef(music.source, AL_GAIN, 1);
|
||||||
|
alSource3f(music.source, AL_POSITION, 0, 0, 0);
|
||||||
|
alSource3f(music.source, AL_VELOCITY, 0, 0, 0);
|
||||||
|
alSourcei(music.source, AL_LOOPING, AL_TRUE); // We loop by default
|
||||||
|
|
||||||
|
// Convert loaded data to OpenAL buffers
|
||||||
|
alGenBuffers(2, music.buffers);
|
||||||
|
/*
|
||||||
|
if (!MusicStream(music, music.buffers[0])) exit(1);
|
||||||
|
if (!MusicStream(music, music.buffers[1])) exit(1);
|
||||||
|
|
||||||
|
alSourceQueueBuffers(music.source, 2, music.buffers);
|
||||||
|
|
||||||
|
PlayMusic(music);
|
||||||
|
*/
|
||||||
|
music.totalSamplesLeft = stb_vorbis_stream_length_in_samples(music.stream) * music.info.channels;
|
||||||
|
|
||||||
|
currentMusic = &music;
|
||||||
|
}
|
||||||
|
|
||||||
|
return music;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnloadMusic(Music music)
|
||||||
|
{
|
||||||
|
StopMusic(music);
|
||||||
|
|
||||||
|
alDeleteSources(1, &music.source);
|
||||||
|
alDeleteBuffers(2, music.buffers);
|
||||||
|
|
||||||
|
stb_vorbis_close(music.stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayMusic(Music music)
|
||||||
|
{
|
||||||
|
//if (MusicIsPlaying(music)) return true;
|
||||||
|
|
||||||
|
if (!MusicStream(music, music.buffers[0])) TraceLog(WARNING, "MusicStream returned 0");
|
||||||
|
if (!MusicStream(music, music.buffers[1])) TraceLog(WARNING, "MusicStream returned 0");
|
||||||
|
|
||||||
|
alSourceQueueBuffers(music.source, 2, music.buffers);
|
||||||
|
alSourcePlay(music.source);
|
||||||
|
|
||||||
|
TraceLog(INFO, "Playing music");
|
||||||
|
}
|
||||||
|
|
||||||
|
extern void PlayCurrentMusic()
|
||||||
|
{
|
||||||
|
if (!MusicStream(*currentMusic, currentMusic->buffers[0])) TraceLog(WARNING, "MusicStream returned 0");
|
||||||
|
if (!MusicStream(*currentMusic, currentMusic->buffers[1])) TraceLog(WARNING, "MusicStream returned 0");
|
||||||
|
|
||||||
|
alSourceQueueBuffers(currentMusic->source, 2, currentMusic->buffers);
|
||||||
|
alSourcePlay(currentMusic->source);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop reproducing music
|
||||||
|
void StopMusic(Music music)
|
||||||
|
{
|
||||||
|
alSourceStop(music.source);
|
||||||
|
|
||||||
|
musicIsPlaying = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool MusicStream(Music music, ALuint buffer)
|
||||||
|
{
|
||||||
|
//Uncomment this to avoid VLAs
|
||||||
|
//#define BUFFER_SIZE 4096*32
|
||||||
|
#ifndef BUFFER_SIZE//VLAs ftw
|
||||||
|
#define BUFFER_SIZE (music.bufferSize)
|
||||||
|
#endif
|
||||||
|
ALshort pcm[BUFFER_SIZE];
|
||||||
|
|
||||||
|
int size = 0;
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
while (size < BUFFER_SIZE)
|
||||||
|
{
|
||||||
|
result = stb_vorbis_get_samples_short_interleaved(music.stream, music.info.channels, pcm+size, BUFFER_SIZE-size);
|
||||||
|
|
||||||
|
if (result > 0) size += (result*music.info.channels);
|
||||||
|
else break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size == 0) return false;
|
||||||
|
|
||||||
|
alBufferData(buffer, music.format, pcm, size*sizeof(ALshort), music.info.sample_rate);
|
||||||
|
|
||||||
|
music.totalSamplesLeft -= size;
|
||||||
|
|
||||||
|
#undef BUFFER_SIZE
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
extern bool MusicStreamUpdate()
|
||||||
|
{
|
||||||
|
ALint processed = 0;
|
||||||
|
|
||||||
|
alGetSourcei(currentMusic->source, AL_BUFFERS_PROCESSED, &processed);
|
||||||
|
|
||||||
|
while (processed--)
|
||||||
|
{
|
||||||
|
ALuint buffer = 0;
|
||||||
|
|
||||||
|
alSourceUnqueueBuffers(currentMusic->source, 1, &buffer);
|
||||||
|
|
||||||
|
if (!MusicStream(*currentMusic, buffer))
|
||||||
|
{
|
||||||
|
bool shouldExit = true;
|
||||||
|
|
||||||
|
if (currentMusic->loop)
|
||||||
|
{
|
||||||
|
stb_vorbis_seek_start(currentMusic->stream);
|
||||||
|
currentMusic->totalSamplesLeft = stb_vorbis_stream_length_in_samples(currentMusic->stream) * currentMusic->info.channels;
|
||||||
|
|
||||||
|
shouldExit = !MusicStream(*currentMusic, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldExit) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
alSourceQueueBuffers(currentMusic->source, 1, &buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
extern bool MusicStreamUpdate()
|
||||||
|
{
|
||||||
|
int processed;
|
||||||
|
bool active = true;
|
||||||
|
|
||||||
|
alGetSourcei(currentMusic->source, AL_BUFFERS_PROCESSED, &processed);
|
||||||
|
|
||||||
|
printf("Data processed: %i\n", processed);
|
||||||
|
|
||||||
|
while (processed--)
|
||||||
|
{
|
||||||
|
ALuint buffer = 0;
|
||||||
|
|
||||||
|
alSourceUnqueueBuffers(currentMusic->source, 1, &buffer);
|
||||||
|
|
||||||
|
active = MusicStream(*currentMusic, buffer);
|
||||||
|
|
||||||
|
alSourceQueueBuffers(currentMusic->source, 1, &buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
return active;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MusicStreamEmpty()
|
||||||
|
{
|
||||||
|
int queued;
|
||||||
|
|
||||||
|
alGetSourcei(currentMusic->source, AL_BUFFERS_QUEUED, &queued);
|
||||||
|
|
||||||
|
while(queued--)
|
||||||
|
{
|
||||||
|
ALuint buffer;
|
||||||
|
alSourceUnqueueBuffers(currentMusic->source, 1, &buffer);
|
||||||
|
}
|
||||||
|
}
|
320
src/core.c
320
src/core.c
|
@ -28,15 +28,19 @@
|
||||||
|
|
||||||
#include "raylib.h"
|
#include "raylib.h"
|
||||||
|
|
||||||
|
#include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3+ or ES2
|
||||||
|
|
||||||
#include <GLFW/glfw3.h> // GLFW3 lib: Windows, OpenGL context and Input management
|
#include <GLFW/glfw3.h> // GLFW3 lib: Windows, OpenGL context and Input management
|
||||||
//#include <GL/gl.h> // OpenGL functions (GLFW3 already includes gl.h)
|
//#include <GL/gl.h> // OpenGL functions (GLFW3 already includes gl.h)
|
||||||
#include <stdio.h> // Standard input / output lib
|
#include <stdio.h> // Standard input / output lib
|
||||||
#include <stdlib.h> // Declares malloc() and free() for memory management, rand()
|
#include <stdlib.h> // Declares malloc() and free() for memory management, rand()
|
||||||
#include <time.h> // Useful to initialize random seed
|
#include <time.h> // Useful to initialize random seed
|
||||||
#include <math.h> // Math related functions, tan() used to set perspective
|
#include <math.h> // Math related functions, tan() used to set perspective
|
||||||
#include "vector3.h" // Basic Vector3 functions
|
//#include "vector3.h" // Basic Vector3 functions, not required any more, replaced by raymath
|
||||||
#include "utils.h" // WritePNG() function
|
#include "utils.h" // WritePNG() function
|
||||||
|
|
||||||
|
#include "raymath.h" // Required for data type Matrix and Matrix functions
|
||||||
|
|
||||||
//#define GLFW_DLL // Using GLFW DLL on Windows -> No, we use static version!
|
//#define GLFW_DLL // Using GLFW DLL on Windows -> No, we use static version!
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
@ -47,7 +51,7 @@
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Types and Structures Definition
|
// Types and Structures Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
typedef Color pixel;
|
// ...
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Global Variables Definition
|
// Global Variables Definition
|
||||||
|
@ -62,7 +66,7 @@ static double targetTime = 0; // Desired time for one frame, if 0
|
||||||
|
|
||||||
static int windowWidth, windowHeight; // Required to switch between windowed/fullscren mode (F11)
|
static int windowWidth, windowHeight; // Required to switch between windowed/fullscren mode (F11)
|
||||||
static const char *windowTitle; // Required to switch between windowed/fullscren mode (F11)
|
static const char *windowTitle; // Required to switch between windowed/fullscren mode (F11)
|
||||||
static int exitKey = GLFW_KEY_ESCAPE;
|
static int exitKey = GLFW_KEY_ESCAPE; // Default exit key (ESC)
|
||||||
|
|
||||||
static bool customCursor = false; // Tracks if custom cursor has been set
|
static bool customCursor = false; // Tracks if custom cursor has been set
|
||||||
static bool cursorOnScreen = false; // Tracks if cursor is inside client area
|
static bool cursorOnScreen = false; // Tracks if cursor is inside client area
|
||||||
|
@ -77,8 +81,10 @@ static char currentMouseState[3] = { 0 }; // Required to check if mouse btn pr
|
||||||
static char previousGamepadState[32] = {0}; // Required to check if gamepad btn pressed/released once
|
static char previousGamepadState[32] = {0}; // Required to check if gamepad btn pressed/released once
|
||||||
static char currentGamepadState[32] = {0}; // Required to check if gamepad btn pressed/released once
|
static char currentGamepadState[32] = {0}; // Required to check if gamepad btn pressed/released once
|
||||||
|
|
||||||
static int previousMouseWheelY = 0;
|
static int previousMouseWheelY = 0; // Required to track mouse wheel variation
|
||||||
static int currentMouseWheelY = 0;
|
static int currentMouseWheelY = 0; // Required to track mouse wheel variation
|
||||||
|
|
||||||
|
static Color background = { 0, 0, 0, 0 }; // Screen background color
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Other Modules Functions Declaration (required by core)
|
// Other Modules Functions Declaration (required by core)
|
||||||
|
@ -86,16 +92,17 @@ static int currentMouseWheelY = 0;
|
||||||
extern void LoadDefaultFont(); // [Module: text] Loads default font on InitWindow()
|
extern void LoadDefaultFont(); // [Module: text] Loads default font on InitWindow()
|
||||||
extern void UnloadDefaultFont(); // [Module: text] Unloads default font from GPU memory
|
extern void UnloadDefaultFont(); // [Module: text] Unloads default font from GPU memory
|
||||||
|
|
||||||
|
extern bool MusicStreamUpdate(); // [Module: audio] Updates buffers for music streamming
|
||||||
|
extern void PlayCurrentMusic(); // [Module: audio] Plays current music stream
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module specific Functions Declaration
|
// Module specific Functions Declaration
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
static void InitGraphicsDevice(); // Initialize Graphics Device (OpenGL stuff)
|
|
||||||
static void ErrorCallback(int error, const char *description); // GLFW3 Error Callback, runs on GLFW3 error
|
static void ErrorCallback(int error, const char *description); // GLFW3 Error Callback, runs on GLFW3 error
|
||||||
static void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods); // GLFW3 Keyboard Callback, runs on key pressed
|
static void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods); // GLFW3 Keyboard Callback, runs on key pressed
|
||||||
static void ScrollCallback(GLFWwindow* window, double xoffset, double yoffset); // GLFW3 Srolling Callback, runs on mouse wheel
|
static void ScrollCallback(GLFWwindow* window, double xoffset, double yoffset); // GLFW3 Srolling Callback, runs on mouse wheel
|
||||||
static void CursorEnterCallback(GLFWwindow* window, int enter); // GLFW3 Cursor Enter Callback, cursor enters client area
|
static void CursorEnterCallback(GLFWwindow* window, int enter); // GLFW3 Cursor Enter Callback, cursor enters client area
|
||||||
static void WindowSizeCallback(GLFWwindow* window, int width, int height); // GLFW3 WindowSize Callback, runs when window is resized
|
static void WindowSizeCallback(GLFWwindow* window, int width, int height); // GLFW3 WindowSize Callback, runs when window is resized
|
||||||
static void CameraLookAt(Vector3 position, Vector3 target, Vector3 up); // Setup camera view (updates MODELVIEW matrix)
|
|
||||||
static void TakeScreenshot(); // Takes a bitmap (BMP) screenshot and saves it in the same folder as executable
|
static void TakeScreenshot(); // Takes a bitmap (BMP) screenshot and saves it in the same folder as executable
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
@ -113,12 +120,20 @@ void InitWindowEx(int width, int height, const char* title, bool resizable, cons
|
||||||
{
|
{
|
||||||
glfwSetErrorCallback(ErrorCallback);
|
glfwSetErrorCallback(ErrorCallback);
|
||||||
|
|
||||||
if (!glfwInit()) exit(1);
|
if (!glfwInit()) TraceLog(ERROR, "Failed to initialize GLFW");
|
||||||
|
|
||||||
//glfwDefaultWindowHints() // Set default windows hints
|
//glfwDefaultWindowHints() // Set default windows hints
|
||||||
//glfwWindowHint(GLFW_SAMPLES, 4); // If called before windows creation, enables multisampling x4 (MSAA), default is 0
|
|
||||||
if (!resizable) glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); // Avoid window being resizable
|
if (!resizable) glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); // Avoid window being resizable
|
||||||
|
|
||||||
|
#ifdef USE_OPENGL_33
|
||||||
|
//glfwWindowHint(GLFW_SAMPLES, 4); // Enables multisampling x4 (MSAA), default is 0
|
||||||
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||||
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||||
|
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||||
|
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_FALSE);
|
||||||
|
#endif
|
||||||
|
|
||||||
window = glfwCreateWindow(width, height, title, NULL, NULL);
|
window = glfwCreateWindow(width, height, title, NULL, NULL);
|
||||||
|
|
||||||
windowWidth = width;
|
windowWidth = width;
|
||||||
|
@ -128,7 +143,7 @@ void InitWindowEx(int width, int height, const char* title, bool resizable, cons
|
||||||
if (!window)
|
if (!window)
|
||||||
{
|
{
|
||||||
glfwTerminate();
|
glfwTerminate();
|
||||||
exit(1);
|
TraceLog(ERROR, "Failed to initialize Window");
|
||||||
}
|
}
|
||||||
|
|
||||||
glfwSetWindowSizeCallback(window, WindowSizeCallback);
|
glfwSetWindowSizeCallback(window, WindowSizeCallback);
|
||||||
|
@ -140,21 +155,41 @@ void InitWindowEx(int width, int height, const char* title, bool resizable, cons
|
||||||
glfwSwapInterval(0); // Disables GPU v-sync (if set), so frames are not limited to screen refresh rate (60Hz -> 60 FPS)
|
glfwSwapInterval(0); // Disables GPU v-sync (if set), so frames are not limited to screen refresh rate (60Hz -> 60 FPS)
|
||||||
// If not set, swap interval uses GPU v-sync configuration
|
// If not set, swap interval uses GPU v-sync configuration
|
||||||
// Framerate can be setup using SetTargetFPS()
|
// Framerate can be setup using SetTargetFPS()
|
||||||
InitGraphicsDevice();
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
#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();
|
previousTime = glfwGetTime();
|
||||||
|
|
||||||
LoadDefaultFont();
|
LoadDefaultFont(); // NOTE: External function (defined in module: text)
|
||||||
|
|
||||||
if (cursorImage != NULL) SetCustomCursor(cursorImage);
|
if (cursorImage != NULL) SetCustomCursor(cursorImage);
|
||||||
|
|
||||||
srand(time(NULL)); // Initialize random seed
|
srand(time(NULL)); // Initialize random seed
|
||||||
|
|
||||||
|
ClearBackground(RAYWHITE); // Default background color for raylib games :P
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close Window and Terminate Context
|
// Close Window and Terminate Context
|
||||||
void CloseWindow()
|
void CloseWindow()
|
||||||
{
|
{
|
||||||
UnloadDefaultFont();
|
UnloadDefaultFont();
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
#if defined(USE_OPENGL_33) || defined(USE_OPENGL_ES2)
|
||||||
|
rlglClose(); // De-init rlgl
|
||||||
|
#endif
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
glfwDestroyWindow(window);
|
glfwDestroyWindow(window);
|
||||||
glfwTerminate();
|
glfwTerminate();
|
||||||
|
@ -198,19 +233,30 @@ void ToggleFullscreen()
|
||||||
// TODO: WARNING! All loaded resources are lost, we loose Context!
|
// TODO: WARNING! All loaded resources are lost, we loose Context!
|
||||||
|
|
||||||
// NOTE: Window aspect ratio is always windowWidth / windowHeight
|
// NOTE: Window aspect ratio is always windowWidth / windowHeight
|
||||||
if (fullscreen) window = glfwCreateWindow(windowWidth, windowHeight, windowTitle, glfwGetPrimaryMonitor(), NULL); // Fullscreen mode
|
if (fullscreen)
|
||||||
|
{
|
||||||
|
// TODO: Get desktop window size and adapt aspect-ratio (?)
|
||||||
|
//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);
|
else window = glfwCreateWindow(windowWidth, windowHeight, windowTitle, NULL, NULL);
|
||||||
|
|
||||||
if (!window)
|
if (!window)
|
||||||
{
|
{
|
||||||
glfwTerminate();
|
glfwTerminate();
|
||||||
exit(1);
|
TraceLog(ERROR, "Failed to initialize Window when switching fullscreen mode");
|
||||||
}
|
}
|
||||||
|
|
||||||
glfwMakeContextCurrent(window);
|
glfwMakeContextCurrent(window);
|
||||||
glfwSetKeyCallback(window, KeyCallback);
|
glfwSetKeyCallback(window, KeyCallback);
|
||||||
|
|
||||||
InitGraphicsDevice();
|
int fbWidth, fbHeight;
|
||||||
|
glfwGetFramebufferSize(window, &fbWidth, &fbHeight); // Get framebuffer size of current window
|
||||||
|
|
||||||
|
rlglInitGraphicsDevice(fbWidth, fbHeight);
|
||||||
|
|
||||||
LoadDefaultFont();
|
LoadDefaultFont();
|
||||||
}
|
}
|
||||||
|
@ -219,13 +265,12 @@ void ToggleFullscreen()
|
||||||
// Sets Background Color
|
// Sets Background Color
|
||||||
void ClearBackground(Color color)
|
void ClearBackground(Color color)
|
||||||
{
|
{
|
||||||
// Color values clamp to 0.0f(0) and 1.0f(255)
|
if ((color.r != background.r) || (color.g != background.g) || (color.b != background.b) || (color.a != background.a))
|
||||||
float r = (float)color.r / 255;
|
{
|
||||||
float g = (float)color.g / 255;
|
rlClearColor(color.r, color.g, color.b, color.a);
|
||||||
float b = (float)color.b / 255;
|
|
||||||
float a = (float)color.a / 255;
|
background = color;
|
||||||
|
}
|
||||||
glClearColor(r, g, b, a);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup drawing canvas to start drawing
|
// Setup drawing canvas to start drawing
|
||||||
|
@ -235,11 +280,14 @@ void BeginDrawing()
|
||||||
updateTime = currentTime - previousTime;
|
updateTime = currentTime - previousTime;
|
||||||
previousTime = currentTime;
|
previousTime = currentTime;
|
||||||
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear used buffers, Depth Buffer is used for 3D
|
rlClearScreenBuffers();
|
||||||
|
|
||||||
glLoadIdentity(); // Reset current matrix (MODELVIEW)
|
rlLoadIdentity(); // Reset current matrix (MODELVIEW)
|
||||||
|
|
||||||
glTranslatef(0.375, 0.375, 0); // HACK to have 2D pixel-perfect drawing on OpenGL
|
//#ifdef USE_OPENGL_11
|
||||||
|
// rlTranslatef(0.375, 0.375, 0); // HACK to have 2D pixel-perfect drawing on OpenGL
|
||||||
|
// NOTE: Not required with OpenGL 3.3+
|
||||||
|
//#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// End canvas drawing and Swap Buffers (Double Buffering)
|
// End canvas drawing and Swap Buffers (Double Buffering)
|
||||||
|
@ -247,9 +295,19 @@ void EndDrawing()
|
||||||
{
|
{
|
||||||
if (customCursor && cursorOnScreen) DrawTexture(cursor, GetMouseX(), GetMouseY(), WHITE);
|
if (customCursor && cursorOnScreen) DrawTexture(cursor, GetMouseX(), GetMouseY(), WHITE);
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
#if defined(USE_OPENGL_33) || defined(USE_OPENGL_ES2)
|
||||||
|
rlglDraw(); // Draw Buffers
|
||||||
|
#endif
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
glfwSwapBuffers(window); // Swap back and front buffers
|
glfwSwapBuffers(window); // Swap back and front buffers
|
||||||
glfwPollEvents(); // Register keyboard/mouse events
|
glfwPollEvents(); // Register keyboard/mouse events
|
||||||
|
|
||||||
|
//MusicStreamUpdate();
|
||||||
|
//if (!MusicIsPlaying())
|
||||||
|
//PlayCurrentMusic();
|
||||||
|
|
||||||
currentTime = glfwGetTime();
|
currentTime = glfwGetTime();
|
||||||
drawTime = currentTime - previousTime;
|
drawTime = currentTime - previousTime;
|
||||||
previousTime = currentTime;
|
previousTime = currentTime;
|
||||||
|
@ -271,34 +329,48 @@ void EndDrawing()
|
||||||
// Initializes 3D mode for drawing (Camera setup)
|
// Initializes 3D mode for drawing (Camera setup)
|
||||||
void Begin3dMode(Camera camera)
|
void Begin3dMode(Camera camera)
|
||||||
{
|
{
|
||||||
glMatrixMode(GL_PROJECTION); // Switch to projection matrix
|
//------------------------------------------------------
|
||||||
|
#if defined(USE_OPENGL_33) || defined(USE_OPENGL_ES2)
|
||||||
|
rlglDraw(); // Draw Buffers
|
||||||
|
#endif
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
rlMatrixMode(RL_PROJECTION); // Switch to projection matrix
|
||||||
|
|
||||||
glPushMatrix(); // Save previous matrix, which contains the settings for the 2d ortho projection
|
rlPushMatrix(); // Save previous matrix, which contains the settings for the 2d ortho projection
|
||||||
glLoadIdentity(); // Reset current matrix (PROJECTION)
|
rlLoadIdentity(); // Reset current matrix (PROJECTION)
|
||||||
|
|
||||||
// Setup perspective projection
|
// Setup perspective projection
|
||||||
float aspect = (GLfloat)windowWidth/(GLfloat)windowHeight;
|
float aspect = (GLfloat)windowWidth/(GLfloat)windowHeight;
|
||||||
double top = 0.1f*tan(45.0f*PI / 360.0);
|
double top = 0.1f*tan(45.0f*PI / 360.0);
|
||||||
double right = top*aspect;
|
double right = top*aspect;
|
||||||
|
|
||||||
glFrustum(-right, right, -top, top, 0.1f, 100.0f);
|
rlFrustum(-right, right, -top, top, 0.1f, 100.0f);
|
||||||
|
|
||||||
glMatrixMode(GL_MODELVIEW); // Switch back to modelview matrix
|
rlMatrixMode(RL_MODELVIEW); // Switch back to modelview matrix
|
||||||
glLoadIdentity(); // Reset current matrix (MODELVIEW)
|
rlLoadIdentity(); // Reset current matrix (MODELVIEW)
|
||||||
|
|
||||||
CameraLookAt(camera.position, camera.target, camera.up); // Setup Camera view
|
// Setup Camera view
|
||||||
|
Matrix matLookAt = MatrixLookAt(camera.position, camera.target, camera.up);
|
||||||
|
rlMultMatrixf(GetMatrixVector(matLookAt)); // Multiply MODELVIEW matrix by view matrix (camera)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ends 3D mode and returns to default 2D orthographic mode
|
// Ends 3D mode and returns to default 2D orthographic mode
|
||||||
void End3dMode()
|
void End3dMode()
|
||||||
{
|
{
|
||||||
glMatrixMode(GL_PROJECTION); // Switch to projection matrix
|
//------------------------------------------------------
|
||||||
glPopMatrix(); // Restore previous matrix (PROJECTION) from matrix stack
|
#if defined(USE_OPENGL_33) || defined(USE_OPENGL_ES2)
|
||||||
|
rlglDraw(); // Draw Buffers
|
||||||
|
#endif
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
rlMatrixMode(RL_PROJECTION); // Switch to projection matrix
|
||||||
|
rlPopMatrix(); // Restore previous matrix (PROJECTION) from matrix stack
|
||||||
|
|
||||||
glMatrixMode(GL_MODELVIEW); // Get back to modelview matrix
|
rlMatrixMode(RL_MODELVIEW); // Get back to modelview matrix
|
||||||
glLoadIdentity(); // Reset current matrix (MODELVIEW)
|
rlLoadIdentity(); // Reset current matrix (MODELVIEW)
|
||||||
|
|
||||||
glTranslatef(0.375, 0.375, 0); // HACK to ensure pixel-perfect drawing on OpenGL (after exiting 3D mode)
|
//rlTranslatef(0.375, 0.375, 0); // HACK to ensure pixel-perfect drawing on OpenGL (after exiting 3D mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set target FPS for the game
|
// Set target FPS for the game
|
||||||
|
@ -306,7 +378,7 @@ void SetTargetFPS(int fps)
|
||||||
{
|
{
|
||||||
targetTime = 1 / (float)fps;
|
targetTime = 1 / (float)fps;
|
||||||
|
|
||||||
printf("TargetTime per Frame: %f seconds\n", (float)targetTime);
|
TraceLog(INFO, "Target time per frame: %02.03f milliseconds", (float)targetTime*1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns current FPS
|
// Returns current FPS
|
||||||
|
@ -374,18 +446,18 @@ Color Fade(Color color, float alpha)
|
||||||
// Detect if a key has been pressed once
|
// Detect if a key has been pressed once
|
||||||
bool IsKeyPressed(int key)
|
bool IsKeyPressed(int key)
|
||||||
{
|
{
|
||||||
bool ret = false;
|
bool pressed = false;
|
||||||
|
|
||||||
currentKeyState[key] = IsKeyDown(key);
|
currentKeyState[key] = IsKeyDown(key);
|
||||||
|
|
||||||
if (currentKeyState[key] != previousKeyState[key])
|
if (currentKeyState[key] != previousKeyState[key])
|
||||||
{
|
{
|
||||||
if (currentKeyState[key]) ret = true;
|
if (currentKeyState[key]) pressed = true;
|
||||||
previousKeyState[key] = currentKeyState[key];
|
previousKeyState[key] = currentKeyState[key];
|
||||||
}
|
}
|
||||||
else ret = false;
|
else pressed = false;
|
||||||
|
|
||||||
return ret;
|
return pressed;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Detect if a key is being pressed (key held down)
|
// Detect if a key is being pressed (key held down)
|
||||||
|
@ -398,18 +470,18 @@ bool IsKeyDown(int key)
|
||||||
// Detect if a key has been released once
|
// Detect if a key has been released once
|
||||||
bool IsKeyReleased(int key)
|
bool IsKeyReleased(int key)
|
||||||
{
|
{
|
||||||
bool ret = false;
|
bool released = false;
|
||||||
|
|
||||||
currentKeyState[key] = IsKeyUp(key);
|
currentKeyState[key] = IsKeyUp(key);
|
||||||
|
|
||||||
if (currentKeyState[key] != previousKeyState[key])
|
if (currentKeyState[key] != previousKeyState[key])
|
||||||
{
|
{
|
||||||
if (currentKeyState[key]) ret = true;
|
if (currentKeyState[key]) released = true;
|
||||||
previousKeyState[key] = currentKeyState[key];
|
previousKeyState[key] = currentKeyState[key];
|
||||||
}
|
}
|
||||||
else ret = false;
|
else released = false;
|
||||||
|
|
||||||
return ret;
|
return released;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Detect if a key is NOT being pressed (key not held down)
|
// Detect if a key is NOT being pressed (key not held down)
|
||||||
|
@ -422,18 +494,18 @@ bool IsKeyUp(int key)
|
||||||
// Detect if a mouse button has been pressed once
|
// Detect if a mouse button has been pressed once
|
||||||
bool IsMouseButtonPressed(int button)
|
bool IsMouseButtonPressed(int button)
|
||||||
{
|
{
|
||||||
bool ret = false;
|
bool pressed = false;
|
||||||
|
|
||||||
currentMouseState[button] = IsMouseButtonDown(button);
|
currentMouseState[button] = IsMouseButtonDown(button);
|
||||||
|
|
||||||
if (currentMouseState[button] != previousMouseState[button])
|
if (currentMouseState[button] != previousMouseState[button])
|
||||||
{
|
{
|
||||||
if (currentMouseState[button]) ret = true;
|
if (currentMouseState[button]) pressed = true;
|
||||||
previousMouseState[button] = currentMouseState[button];
|
previousMouseState[button] = currentMouseState[button];
|
||||||
}
|
}
|
||||||
else ret = false;
|
else pressed = false;
|
||||||
|
|
||||||
return ret;
|
return pressed;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Detect if a mouse button is being pressed
|
// Detect if a mouse button is being pressed
|
||||||
|
@ -446,18 +518,18 @@ bool IsMouseButtonDown(int button)
|
||||||
// Detect if a mouse button has been released once
|
// Detect if a mouse button has been released once
|
||||||
bool IsMouseButtonReleased(int button)
|
bool IsMouseButtonReleased(int button)
|
||||||
{
|
{
|
||||||
bool ret = false;
|
bool released = false;
|
||||||
|
|
||||||
currentMouseState[button] = IsMouseButtonUp(button);
|
currentMouseState[button] = IsMouseButtonUp(button);
|
||||||
|
|
||||||
if (currentMouseState[button] != previousMouseState[button])
|
if (currentMouseState[button] != previousMouseState[button])
|
||||||
{
|
{
|
||||||
if (currentMouseState[button]) ret = true;
|
if (currentMouseState[button]) released = true;
|
||||||
previousMouseState[button] = currentMouseState[button];
|
previousMouseState[button] = currentMouseState[button];
|
||||||
}
|
}
|
||||||
else ret = false;
|
else released = false;
|
||||||
|
|
||||||
return ret;
|
return released;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Detect if a mouse button is NOT being pressed
|
// Detect if a mouse button is NOT being pressed
|
||||||
|
@ -546,18 +618,18 @@ Vector2 GetGamepadMovement(int gamepad)
|
||||||
// Detect if a gamepad button is being pressed
|
// Detect if a gamepad button is being pressed
|
||||||
bool IsGamepadButtonPressed(int gamepad, int button)
|
bool IsGamepadButtonPressed(int gamepad, int button)
|
||||||
{
|
{
|
||||||
bool ret = false;
|
bool pressed = false;
|
||||||
|
|
||||||
currentGamepadState[button] = IsGamepadButtonDown(gamepad, button);
|
currentGamepadState[button] = IsGamepadButtonDown(gamepad, button);
|
||||||
|
|
||||||
if (currentGamepadState[button] != previousGamepadState[button])
|
if (currentGamepadState[button] != previousGamepadState[button])
|
||||||
{
|
{
|
||||||
if (currentGamepadState[button]) ret = true;
|
if (currentGamepadState[button]) pressed = true;
|
||||||
previousGamepadState[button] = currentGamepadState[button];
|
previousGamepadState[button] = currentGamepadState[button];
|
||||||
}
|
}
|
||||||
else ret = false;
|
else pressed = false;
|
||||||
|
|
||||||
return ret;
|
return pressed;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsGamepadButtonDown(int gamepad, int button)
|
bool IsGamepadButtonDown(int gamepad, int button)
|
||||||
|
@ -577,18 +649,18 @@ bool IsGamepadButtonDown(int gamepad, int button)
|
||||||
// Detect if a gamepad button is NOT being pressed
|
// Detect if a gamepad button is NOT being pressed
|
||||||
bool IsGamepadButtonReleased(int gamepad, int button)
|
bool IsGamepadButtonReleased(int gamepad, int button)
|
||||||
{
|
{
|
||||||
bool ret = false;
|
bool released = false;
|
||||||
|
|
||||||
currentGamepadState[button] = IsGamepadButtonUp(gamepad, button);
|
currentGamepadState[button] = IsGamepadButtonUp(gamepad, button);
|
||||||
|
|
||||||
if (currentGamepadState[button] != previousGamepadState[button])
|
if (currentGamepadState[button] != previousGamepadState[button])
|
||||||
{
|
{
|
||||||
if (currentGamepadState[button]) ret = true;
|
if (currentGamepadState[button]) released = true;
|
||||||
previousGamepadState[button] = currentGamepadState[button];
|
previousGamepadState[button] = currentGamepadState[button];
|
||||||
}
|
}
|
||||||
else ret = false;
|
else released = false;
|
||||||
|
|
||||||
return ret;
|
return released;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsGamepadButtonUp(int gamepad, int button)
|
bool IsGamepadButtonUp(int gamepad, int button)
|
||||||
|
@ -612,8 +684,7 @@ bool IsGamepadButtonUp(int gamepad, int button)
|
||||||
// GLFW3 Error Callback, runs on GLFW3 error
|
// GLFW3 Error Callback, runs on GLFW3 error
|
||||||
static void ErrorCallback(int error, const char *description)
|
static void ErrorCallback(int error, const char *description)
|
||||||
{
|
{
|
||||||
printf(description);
|
TraceLog(WARNING, "GLFW3 Error: %s", description);
|
||||||
//fprintf(stderr, description);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GLFW3 Srolling Callback, runs on mouse wheel
|
// GLFW3 Srolling Callback, runs on mouse wheel
|
||||||
|
@ -649,125 +720,32 @@ static void CursorEnterCallback(GLFWwindow* window, int enter)
|
||||||
|
|
||||||
// GLFW3 WindowSize Callback, runs when window is resized
|
// GLFW3 WindowSize Callback, runs when window is resized
|
||||||
static void WindowSizeCallback(GLFWwindow* window, int width, int height)
|
static void WindowSizeCallback(GLFWwindow* window, int width, int height)
|
||||||
{
|
|
||||||
InitGraphicsDevice(); // If window is resized, graphics device is re-initialized
|
|
||||||
// NOTE: Aspect ratio does not change, so, image can be deformed
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize Graphics Device (OpenGL stuff)
|
|
||||||
static void InitGraphicsDevice()
|
|
||||||
{
|
{
|
||||||
int fbWidth, fbHeight;
|
int fbWidth, fbHeight;
|
||||||
|
|
||||||
glfwGetFramebufferSize(window, &fbWidth, &fbHeight); // Get framebuffer size of current window
|
glfwGetFramebufferSize(window, &fbWidth, &fbHeight); // Get framebuffer size of current window
|
||||||
|
|
||||||
glViewport(0, 0, fbWidth, fbHeight); // Set viewport width and height
|
// If window is resized, graphics device is re-initialized
|
||||||
|
// NOTE: Aspect ratio does not change, so, image can be deformed
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear used buffers, depth buffer is used for 3D
|
rlglInitGraphicsDevice(fbWidth, fbHeight);
|
||||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Set background color (black)
|
|
||||||
glClearDepth(1.0f); // Clear depth buffer
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
glMatrixMode(GL_PROJECTION); // Switch to PROJECTION matrix
|
|
||||||
glLoadIdentity(); // Reset current matrix (PROJECTION)
|
|
||||||
glOrtho(0, fbWidth, fbHeight, 0, 0, 1); // Config orthographic mode: top-left corner --> (0,0)
|
|
||||||
glMatrixMode(GL_MODELVIEW); // Switch back to MODELVIEW matrix
|
|
||||||
glLoadIdentity(); // Reset current matrix (MODELVIEW)
|
|
||||||
|
|
||||||
// TODO: Review all shapes/models are drawn CCW and enable backface culling
|
|
||||||
|
|
||||||
//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)
|
|
||||||
|
|
||||||
glShadeModel(GL_SMOOTH); // Smooth shading between vertex (vertex colors interpolation)
|
|
||||||
// Possible options: GL_SMOOTH (Color interpolation) or GL_FLAT (no interpolation)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup camera view (updates MODELVIEW matrix)
|
|
||||||
static void CameraLookAt(Vector3 position, Vector3 target, Vector3 up)
|
|
||||||
{
|
|
||||||
float rotMatrix[16]; // Matrix to store camera rotation
|
|
||||||
|
|
||||||
Vector3 rotX, rotY, rotZ; // Vectors to calculate camera rotations X, Y, Z (Euler)
|
|
||||||
|
|
||||||
// Construct rotation matrix from vectors
|
|
||||||
rotZ = VectorSubtract(position, target);
|
|
||||||
VectorNormalize(&rotZ);
|
|
||||||
rotY = up; // Y rotation vector
|
|
||||||
rotX = VectorCrossProduct(rotY, rotZ); // X rotation vector = Y cross Z
|
|
||||||
rotY = VectorCrossProduct(rotZ, rotX); // Recompute Y rotation = Z cross X
|
|
||||||
VectorNormalize(&rotX); // X rotation vector normalization
|
|
||||||
VectorNormalize(&rotY); // Y rotation vector normalization
|
|
||||||
|
|
||||||
rotMatrix[0] = rotX.x;
|
|
||||||
rotMatrix[1] = rotY.x;
|
|
||||||
rotMatrix[2] = rotZ.x;
|
|
||||||
rotMatrix[3] = 0.0f;
|
|
||||||
rotMatrix[4] = rotX.y;
|
|
||||||
rotMatrix[5] = rotY.y;
|
|
||||||
rotMatrix[6] = rotZ.y;
|
|
||||||
rotMatrix[7] = 0.0f;
|
|
||||||
rotMatrix[8] = rotX.z;
|
|
||||||
rotMatrix[9] = rotY.z;
|
|
||||||
rotMatrix[10] = rotZ.z;
|
|
||||||
rotMatrix[11] = 0.0f;
|
|
||||||
rotMatrix[12] = 0.0f;
|
|
||||||
rotMatrix[13] = 0.0f;
|
|
||||||
rotMatrix[14] = 0.0f;
|
|
||||||
rotMatrix[15] = 1.0f;
|
|
||||||
|
|
||||||
glMultMatrixf(rotMatrix); // Multiply MODELVIEW matrix by rotation matrix
|
|
||||||
|
|
||||||
glTranslatef(-position.x, -position.y, -position.z); // Translate eye to position
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Takes a bitmap (BMP) screenshot and saves it in the same folder as executable
|
// Takes a bitmap (BMP) screenshot and saves it in the same folder as executable
|
||||||
static void TakeScreenshot()
|
static void TakeScreenshot()
|
||||||
{
|
{
|
||||||
static int shotNum = 0; // Screenshot number, increments every screenshot take during program execution
|
static int shotNum = 0; // Screenshot number, increments every screenshot take during program execution
|
||||||
|
|
||||||
char buffer[20]; // Buffer to store file name
|
char buffer[20]; // Buffer to store file name
|
||||||
int fbWidth, fbHeight;
|
int fbWidth, fbHeight; // Frame buffer width and height
|
||||||
|
|
||||||
unsigned char *imgData; // Pixel image data array
|
|
||||||
|
|
||||||
glfwGetFramebufferSize(window, &fbWidth, &fbHeight); // Get framebuffer size of current window
|
glfwGetFramebufferSize(window, &fbWidth, &fbHeight); // Get framebuffer size of current window
|
||||||
|
|
||||||
imgData = (unsigned char *)malloc(fbWidth * fbHeight * sizeof(unsigned char) * 4);
|
unsigned char *imgData = rlglReadScreenPixels(fbWidth, fbHeight);
|
||||||
|
|
||||||
// NOTE: glReadPixels returns image flipped vertically -> (0,0) is the bottom left corner of the framebuffer
|
|
||||||
glReadPixels(0, 0, fbWidth, fbHeight, GL_RGBA, GL_UNSIGNED_BYTE, imgData);
|
|
||||||
|
|
||||||
// TODO: Flip image vertically!
|
|
||||||
|
|
||||||
unsigned char *imgDataFlip = (unsigned char *)malloc(fbWidth * fbHeight * sizeof(unsigned char) * 4);
|
|
||||||
|
|
||||||
for (int y = fbHeight-1; y >= 0; y--)
|
|
||||||
{
|
|
||||||
for (int x = 0; x < (fbWidth*4); x++)
|
|
||||||
{
|
|
||||||
imgDataFlip[x + (fbHeight - y - 1)*fbWidth*4] = imgData[x + (y*fbWidth*4)];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
free(imgData);
|
|
||||||
|
|
||||||
sprintf(buffer, "screenshot%03i.png", shotNum);
|
sprintf(buffer, "screenshot%03i.png", shotNum);
|
||||||
|
|
||||||
// NOTE: BMP directly stores data flipped vertically
|
WritePNG(buffer, imgData, fbWidth, fbHeight);
|
||||||
//WriteBitmap(buffer, imgDataPixel, fbWidth, fbHeight); // Writes pixel data array into a bitmap (BMP) file
|
|
||||||
WritePNG(buffer, imgDataFlip, fbWidth, fbHeight);
|
free(imgData);
|
||||||
|
|
||||||
free(imgDataFlip);
|
|
||||||
|
|
||||||
shotNum++;
|
shotNum++;
|
||||||
}
|
}
|
1145
src/models.c
1145
src/models.c
File diff suppressed because it is too large
Load diff
100
src/raylib.h
100
src/raylib.h
|
@ -1,15 +1,17 @@
|
||||||
/*********************************************************************************************
|
/*********************************************************************************************
|
||||||
*
|
*
|
||||||
* raylib 1.0.6 (www.raylib.com)
|
* raylib 1.1 (www.raylib.com)
|
||||||
*
|
*
|
||||||
* A simple and easy-to-use library to learn videogames programming
|
* A simple and easy-to-use library to learn videogames programming
|
||||||
*
|
*
|
||||||
* Features:
|
* Features:
|
||||||
* Library written in plain C code (C99)
|
* Library written in plain C code (C99)
|
||||||
* Uses C# PascalCase/camelCase notation
|
* Uses C# PascalCase/camelCase notation
|
||||||
* Hardware accelerated with OpenGL 1.1
|
* Hardware accelerated with OpenGL (1.1, 3.3+ or ES2)
|
||||||
|
* Unique OpenGL abstraction layer [rlgl]
|
||||||
* Powerful fonts module with SpriteFonts support
|
* Powerful fonts module with SpriteFonts support
|
||||||
* Basic 3d support for Shapes and Models
|
* Basic 3d support for Shapes, Models, Heightmaps and Billboards
|
||||||
|
* Powerful math module for Vector and Matrix operations [raymath]
|
||||||
* Audio loading and playing
|
* Audio loading and playing
|
||||||
*
|
*
|
||||||
* Used external libs:
|
* Used external libs:
|
||||||
|
@ -23,8 +25,9 @@
|
||||||
* 32bit Textures - All loaded images are converted automatically to RGBA textures
|
* 32bit Textures - All loaded images are converted automatically to RGBA textures
|
||||||
* SpriteFonts - All loaded sprite-font images are converted to RGBA and POT textures
|
* SpriteFonts - All loaded sprite-font images are converted to RGBA and POT textures
|
||||||
* One custom default font is loaded automatically when InitWindow()
|
* One custom default font is loaded automatically when InitWindow()
|
||||||
|
* If using OpenGL 3.3+, one default shader is loaded automatically (internally defined)
|
||||||
*
|
*
|
||||||
* -- LICENSE (raylib v1.0, November 2013) --
|
* -- LICENSE (raylib v1.1, March 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:
|
* BSD-like license that allows static linking with closed source software:
|
||||||
|
@ -51,6 +54,8 @@
|
||||||
#ifndef RAYLIB_H
|
#ifndef RAYLIB_H
|
||||||
#define RAYLIB_H
|
#define RAYLIB_H
|
||||||
|
|
||||||
|
#include "stb_vorbis.h"
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Some basic Defines
|
// Some basic Defines
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
@ -150,6 +155,19 @@
|
||||||
// Boolean type
|
// Boolean type
|
||||||
typedef enum { false, true } bool;
|
typedef enum { false, true } bool;
|
||||||
|
|
||||||
|
// Vector2 type
|
||||||
|
typedef struct Vector2 {
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
} Vector2;
|
||||||
|
|
||||||
|
// Vector3 type
|
||||||
|
typedef struct Vector3 {
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
float z;
|
||||||
|
} Vector3;
|
||||||
|
|
||||||
// Color type, RGBA (32bit)
|
// Color type, RGBA (32bit)
|
||||||
typedef struct Color {
|
typedef struct Color {
|
||||||
unsigned char r;
|
unsigned char r;
|
||||||
|
@ -182,29 +200,6 @@ typedef struct Texture2D {
|
||||||
int height;
|
int height;
|
||||||
} Texture2D;
|
} Texture2D;
|
||||||
|
|
||||||
// SpriteFont one Character (Glyph) data, defined in text module
|
|
||||||
typedef struct Character Character;
|
|
||||||
|
|
||||||
// SpriteFont type, includes texture and charSet array data
|
|
||||||
typedef struct SpriteFont {
|
|
||||||
Texture2D texture;
|
|
||||||
int numChars;
|
|
||||||
Character *charSet;
|
|
||||||
} SpriteFont;
|
|
||||||
|
|
||||||
// Vector2 type
|
|
||||||
typedef struct Vector2 {
|
|
||||||
float x;
|
|
||||||
float y;
|
|
||||||
} Vector2;
|
|
||||||
|
|
||||||
// Vector3 type
|
|
||||||
typedef struct Vector3 {
|
|
||||||
float x;
|
|
||||||
float y;
|
|
||||||
float z;
|
|
||||||
} Vector3;
|
|
||||||
|
|
||||||
// Camera type, defines a camera position/orientation in 3d space
|
// Camera type, defines a camera position/orientation in 3d space
|
||||||
typedef struct Camera {
|
typedef struct Camera {
|
||||||
Vector3 position;
|
Vector3 position;
|
||||||
|
@ -212,20 +207,42 @@ typedef struct Camera {
|
||||||
Vector3 up;
|
Vector3 up;
|
||||||
} Camera;
|
} Camera;
|
||||||
|
|
||||||
// Basic 3d Model type
|
typedef struct Character Character;
|
||||||
typedef struct Model {
|
|
||||||
int numVertices;
|
|
||||||
Vector3 *vertices;
|
|
||||||
Vector2 *texcoords;
|
|
||||||
Vector3 *normals;
|
|
||||||
} Model;
|
|
||||||
|
|
||||||
// Basic Sound source and buffer
|
// SpriteFont type
|
||||||
|
typedef struct SpriteFont {
|
||||||
|
Texture2D texture;
|
||||||
|
int numChars;
|
||||||
|
Character *charSet;
|
||||||
|
} SpriteFont;
|
||||||
|
|
||||||
|
// 3d Model type
|
||||||
|
// NOTE: If using OpenGL 1.1 loaded in CPU; if OpenGL 3.3+ loaded in GPU
|
||||||
|
typedef struct Model Model; // Defined in module: rlgl
|
||||||
|
|
||||||
|
// Sound source type
|
||||||
typedef struct Sound {
|
typedef struct Sound {
|
||||||
unsigned int source;
|
unsigned int source;
|
||||||
unsigned int buffer;
|
unsigned int buffer;
|
||||||
} Sound;
|
} Sound;
|
||||||
|
|
||||||
|
typedef struct OggStream OggStream;
|
||||||
|
|
||||||
|
// Music type (streamming)
|
||||||
|
typedef struct Music {
|
||||||
|
stb_vorbis *stream;
|
||||||
|
stb_vorbis_info info;
|
||||||
|
|
||||||
|
unsigned int source;
|
||||||
|
unsigned int buffers[2];
|
||||||
|
|
||||||
|
int format;
|
||||||
|
|
||||||
|
int bufferSize;
|
||||||
|
int totalSamplesLeft;
|
||||||
|
bool loop;
|
||||||
|
} Music;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" { // Prevents name mangling of functions
|
extern "C" { // Prevents name mangling of functions
|
||||||
#endif
|
#endif
|
||||||
|
@ -357,15 +374,17 @@ const char *FormatText(const char *text, ...);
|
||||||
void DrawCube(Vector3 position, float width, float height, float lenght, Color color); // Draw cube
|
void DrawCube(Vector3 position, float width, float height, float lenght, Color color); // Draw cube
|
||||||
void DrawCubeV(Vector3 position, Vector3 size, Color color); // Draw cube (Vector version)
|
void DrawCubeV(Vector3 position, Vector3 size, Color color); // Draw cube (Vector version)
|
||||||
void DrawCubeWires(Vector3 position, float width, float height, float lenght, Color color); // Draw cube wires
|
void DrawCubeWires(Vector3 position, float width, float height, float lenght, Color color); // Draw cube wires
|
||||||
|
void DrawCubeTexture(Texture2D texture, Vector3 position, float width, float height, float lenght, Color color); // Draw cube textured
|
||||||
void DrawSphere(Vector3 centerPos, float radius, Color color); // Draw sphere
|
void DrawSphere(Vector3 centerPos, float radius, Color color); // Draw sphere
|
||||||
void DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color color); // Draw sphere with extended parameters
|
void DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color color); // Draw sphere with extended parameters
|
||||||
void DrawSphereWires(Vector3 centerPos, float radius, Color color); // Draw sphere wires
|
void DrawSphereWires(Vector3 centerPos, float radius, int rings, int slices, Color color); // Draw sphere wires
|
||||||
void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float height, int slices, Color color); // Draw a cylinder/cone
|
void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float height, int slices, Color color); // Draw a cylinder/cone
|
||||||
void DrawCylinderWires(Vector3 position, float radiusTop, float radiusBottom, float height, int slices, Color color); // Draw a cylinder/cone wires
|
void DrawCylinderWires(Vector3 position, float radiusTop, float radiusBottom, float height, int slices, Color color); // Draw a cylinder/cone wires
|
||||||
void DrawPlane(Vector3 centerPos, Vector2 size, Vector3 rotation, Color color); // Draw a plane
|
void DrawPlane(Vector3 centerPos, Vector2 size, Vector3 rotation, Color color); // Draw a plane
|
||||||
void DrawPlaneEx(Vector3 centerPos, Vector2 size, Vector3 rotation, int slicesX, int slicesZ, Color color); // Draw a plane with divisions
|
void DrawPlaneEx(Vector3 centerPos, Vector2 size, Vector3 rotation, int slicesX, int slicesZ, Color color); // Draw a plane with divisions
|
||||||
void DrawGrid(int slices, float spacing); // Draw a grid (centered at (0, 0, 0))
|
void DrawGrid(int slices, float spacing); // Draw a grid (centered at (0, 0, 0))
|
||||||
void DrawGizmo(Vector3 position, bool orbits); // Draw gizmo (with or without orbits)
|
void DrawGizmo(Vector3 position); // Draw simple gizmo
|
||||||
|
void DrawGizmoEx(Vector3 position, Vector3 rot, float scale, bool orbits); // Draw gizmo with extended parameters
|
||||||
//DrawTorus(), DrawTeapot() are useless...
|
//DrawTorus(), DrawTeapot() are useless...
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
|
@ -389,13 +408,18 @@ void CloseAudioDevice(); // Close the aud
|
||||||
Sound LoadSound(char *fileName); // Load sound to memory
|
Sound LoadSound(char *fileName); // Load sound to memory
|
||||||
Sound LoadSoundFromRES(const char *rresName, int resId); // Load sound to memory from rRES file (raylib Resource)
|
Sound LoadSoundFromRES(const char *rresName, int resId); // Load sound to memory from rRES file (raylib Resource)
|
||||||
void UnloadSound(Sound sound); // Unload sound
|
void UnloadSound(Sound sound); // Unload sound
|
||||||
|
Music LoadMusic(char *fileName);
|
||||||
|
void UnloadMusic(Music music);
|
||||||
|
|
||||||
void PlaySound(Sound sound); // Play a sound
|
void PlaySound(Sound sound); // Play a sound
|
||||||
void PauseSound(Sound sound); // Pause a sound
|
void PauseSound(Sound sound); // Pause a sound
|
||||||
void StopSound(Sound sound); // Stop playing a sound
|
void StopSound(Sound sound); // Stop playing a sound
|
||||||
bool IsPlaying(Sound sound); // Check if a sound is currently playing
|
bool SoundIsPlaying(Sound sound); // Check if a sound is currently playing
|
||||||
void SetVolume(Sound sound, float volume); // Set volume for a sound (1.0 is base level)
|
void SetVolume(Sound sound, float volume); // Set volume for a sound (1.0 is base level)
|
||||||
void SetPitch(Sound sound, float pitch); // Set pitch for a sound (1.0 is base level)
|
void SetPitch(Sound sound, float pitch); // Set pitch for a sound (1.0 is base level)
|
||||||
|
void PlayMusic(Music music);
|
||||||
|
void StopMusic(Music music);
|
||||||
|
bool MusicIsPlaying();
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
548
src/raymath.c
548
src/raymath.c
|
@ -199,6 +199,28 @@ Vector3 VectorReflect(Vector3 vector, Vector3 normal)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Transforms a Vector3 with a given Matrix
|
||||||
|
void VectorTransform(Vector3 *v, Matrix mat)
|
||||||
|
{
|
||||||
|
float x = v->x;
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Return a Vector3 init to zero
|
||||||
|
Vector3 VectorZero()
|
||||||
|
{
|
||||||
|
Vector3 zero = { 0.0, 0.0, 0.0 };
|
||||||
|
|
||||||
|
return zero;
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module Functions Definition - Matrix math
|
// Module Functions Definition - Matrix math
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
@ -234,17 +256,17 @@ float MatrixDeterminant(Matrix mat)
|
||||||
float result;
|
float result;
|
||||||
|
|
||||||
// Cache the matrix values (speed optimization)
|
// Cache the matrix values (speed optimization)
|
||||||
float a00 = mat.m0, a01 = mat.m1, a02 = mat.m2, a03 = mat.m3;
|
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 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 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 a30 = mat.m12, a31 = mat.m13, a32 = mat.m14, a33 = mat.m15;
|
||||||
|
|
||||||
result = a30*a21*a12*a03 - a20*a31*a12*a03 - a30*a11*a22*a03 + a10*a31*a22*a03 +
|
result = a30*a21*a12*a03 - a20*a31*a12*a03 - a30*a11*a22*a03 + a10*a31*a22*a03 +
|
||||||
a20*a11*a32*a03 - a10*a21*a32*a03 - a30*a21*a02*a13 + a20*a31*a02*a13 +
|
a20*a11*a32*a03 - a10*a21*a32*a03 - a30*a21*a02*a13 + a20*a31*a02*a13 +
|
||||||
a30*a01*a22*a13 - a00*a31*a22*a13 - a20*a01*a32*a13 + a00*a21*a32*a13 +
|
a30*a01*a22*a13 - a00*a31*a22*a13 - a20*a01*a32*a13 + a00*a21*a32*a13 +
|
||||||
a30*a11*a02*a23 - a10*a31*a02*a23 - a30*a01*a12*a23 + a00*a31*a12*a23 +
|
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 +
|
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;
|
a20*a01*a12*a33 - a00*a21*a12*a33 - a10*a01*a22*a33 + a00*a11*a22*a33;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -261,21 +283,21 @@ void MatrixTranspose(Matrix *mat)
|
||||||
Matrix temp;
|
Matrix temp;
|
||||||
|
|
||||||
temp.m0 = mat->m0;
|
temp.m0 = mat->m0;
|
||||||
temp.m1 = mat->m4;
|
temp.m1 = mat->m4;
|
||||||
temp.m2 = mat->m8;
|
temp.m2 = mat->m8;
|
||||||
temp.m3 = mat->m12;
|
temp.m3 = mat->m12;
|
||||||
temp.m4 = mat->m1;
|
temp.m4 = mat->m1;
|
||||||
temp.m5 = mat->m5;
|
temp.m5 = mat->m5;
|
||||||
temp.m6 = mat->m9;
|
temp.m6 = mat->m9;
|
||||||
temp.m7 = mat->m13;
|
temp.m7 = mat->m13;
|
||||||
temp.m8 = mat->m2;
|
temp.m8 = mat->m2;
|
||||||
temp.m9 = mat->m6;
|
temp.m9 = mat->m6;
|
||||||
temp.m10 = mat->m10;
|
temp.m10 = mat->m10;
|
||||||
temp.m11 = mat->m14;
|
temp.m11 = mat->m14;
|
||||||
temp.m12 = mat->m3;
|
temp.m12 = mat->m3;
|
||||||
temp.m13 = mat->m7;
|
temp.m13 = mat->m7;
|
||||||
temp.m14 = mat->m11;
|
temp.m14 = mat->m11;
|
||||||
temp.m15 = mat->m15;
|
temp.m15 = mat->m15;
|
||||||
|
|
||||||
*mat = temp;
|
*mat = temp;
|
||||||
}
|
}
|
||||||
|
@ -285,50 +307,50 @@ void MatrixInvert(Matrix *mat)
|
||||||
{
|
{
|
||||||
Matrix temp;
|
Matrix temp;
|
||||||
|
|
||||||
// Cache the matrix values (speed optimization)
|
// Cache the matrix values (speed optimization)
|
||||||
float a00 = mat->m0, a01 = mat->m1, a02 = mat->m2, a03 = mat->m3;
|
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 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 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 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;
|
|
||||||
float b03 = a01*a12 - a02*a11;
|
|
||||||
float b04 = a01*a13 - a03*a11;
|
|
||||||
float b05 = a02*a13 - a03*a12;
|
|
||||||
float b06 = a20*a31 - a21*a30;
|
|
||||||
float b07 = a20*a32 - a22*a30;
|
|
||||||
float b08 = a20*a33 - a23*a30;
|
|
||||||
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 b00 = a00*a11 - a01*a10;
|
||||||
float invDet = 1/(b00*b11 - b01*b10 + b02*b09 + b03*b08 - b04*b07 + b05*b06);
|
float b01 = a00*a12 - a02*a10;
|
||||||
|
float b02 = a00*a13 - a03*a10;
|
||||||
|
float b03 = a01*a12 - a02*a11;
|
||||||
|
float b04 = a01*a13 - a03*a11;
|
||||||
|
float b05 = a02*a13 - a03*a12;
|
||||||
|
float b06 = a20*a31 - a21*a30;
|
||||||
|
float b07 = a20*a32 - a22*a30;
|
||||||
|
float b08 = a20*a33 - a23*a30;
|
||||||
|
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);
|
printf("%f\n", invDet);
|
||||||
|
|
||||||
temp.m0 = (a11*b11 - a12*b10 + a13*b09)*invDet;
|
temp.m0 = (a11*b11 - a12*b10 + a13*b09)*invDet;
|
||||||
temp.m1 = (-a01*b11 + a02*b10 - a03*b09)*invDet;
|
temp.m1 = (-a01*b11 + a02*b10 - a03*b09)*invDet;
|
||||||
temp.m2 = (a31*b05 - a32*b04 + a33*b03)*invDet;
|
temp.m2 = (a31*b05 - a32*b04 + a33*b03)*invDet;
|
||||||
temp.m3 = (-a21*b05 + a22*b04 - a23*b03)*invDet;
|
temp.m3 = (-a21*b05 + a22*b04 - a23*b03)*invDet;
|
||||||
temp.m4 = (-a10*b11 + a12*b08 - a13*b07)*invDet;
|
temp.m4 = (-a10*b11 + a12*b08 - a13*b07)*invDet;
|
||||||
temp.m5 = (a00*b11 - a02*b08 + a03*b07)*invDet;
|
temp.m5 = (a00*b11 - a02*b08 + a03*b07)*invDet;
|
||||||
temp.m6 = (-a30*b05 + a32*b02 - a33*b01)*invDet;
|
temp.m6 = (-a30*b05 + a32*b02 - a33*b01)*invDet;
|
||||||
temp.m7 = (a20*b05 - a22*b02 + a23*b01)*invDet;
|
temp.m7 = (a20*b05 - a22*b02 + a23*b01)*invDet;
|
||||||
temp.m8 = (a10*b10 - a11*b08 + a13*b06)*invDet;
|
temp.m8 = (a10*b10 - a11*b08 + a13*b06)*invDet;
|
||||||
temp.m9 = (-a00*b10 + a01*b08 - a03*b06)*invDet;
|
temp.m9 = (-a00*b10 + a01*b08 - a03*b06)*invDet;
|
||||||
temp.m10 = (a30*b04 - a31*b02 + a33*b00)*invDet;
|
temp.m10 = (a30*b04 - a31*b02 + a33*b00)*invDet;
|
||||||
temp.m11 = (-a20*b04 + a21*b02 - a23*b00)*invDet;
|
temp.m11 = (-a20*b04 + a21*b02 - a23*b00)*invDet;
|
||||||
temp.m12 = (-a10*b09 + a11*b07 - a12*b06)*invDet;
|
temp.m12 = (-a10*b09 + a11*b07 - a12*b06)*invDet;
|
||||||
temp.m13 = (a00*b09 - a01*b07 + a02*b06)*invDet;
|
temp.m13 = (a00*b09 - a01*b07 + a02*b06)*invDet;
|
||||||
temp.m14 = (-a30*b03 + a31*b01 - a32*b00)*invDet;
|
temp.m14 = (-a30*b03 + a31*b01 - a32*b00)*invDet;
|
||||||
temp.m15 = (a20*b03 - a21*b01 + a22*b00)*invDet;
|
temp.m15 = (a20*b03 - a21*b01 + a22*b00)*invDet;
|
||||||
|
|
||||||
PrintMatrix(temp);
|
PrintMatrix(temp);
|
||||||
|
|
||||||
*mat = temp;
|
*mat = temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Normalize provided matrix
|
// Normalize provided matrix
|
||||||
|
@ -337,21 +359,21 @@ void MatrixNormalize(Matrix *mat)
|
||||||
float det = MatrixDeterminant(*mat);
|
float det = MatrixDeterminant(*mat);
|
||||||
|
|
||||||
mat->m0 /= det;
|
mat->m0 /= det;
|
||||||
mat->m1 /= det;
|
mat->m1 /= det;
|
||||||
mat->m2 /= det;
|
mat->m2 /= det;
|
||||||
mat->m3 /= det;
|
mat->m3 /= det;
|
||||||
mat->m4 /= det;
|
mat->m4 /= det;
|
||||||
mat->m5 /= det;
|
mat->m5 /= det;
|
||||||
mat->m6 /= det;
|
mat->m6 /= det;
|
||||||
mat->m7 /= det;
|
mat->m7 /= det;
|
||||||
mat->m8 /= det;
|
mat->m8 /= det;
|
||||||
mat->m9 /= det;
|
mat->m9 /= det;
|
||||||
mat->m10 /= det;
|
mat->m10 /= det;
|
||||||
mat->m11 /= det;
|
mat->m11 /= det;
|
||||||
mat->m12 /= det;
|
mat->m12 /= det;
|
||||||
mat->m13 /= det;
|
mat->m13 /= det;
|
||||||
mat->m14 /= det;
|
mat->m14 /= det;
|
||||||
mat->m15 /= det;
|
mat->m15 /= det;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns identity matrix
|
// Returns identity matrix
|
||||||
|
@ -368,21 +390,21 @@ Matrix MatrixAdd(Matrix left, Matrix right)
|
||||||
Matrix result = MatrixIdentity();
|
Matrix result = MatrixIdentity();
|
||||||
|
|
||||||
result.m0 = left.m0 + right.m0;
|
result.m0 = left.m0 + right.m0;
|
||||||
result.m1 = left.m1 + right.m1;
|
result.m1 = left.m1 + right.m1;
|
||||||
result.m2 = left.m2 + right.m2;
|
result.m2 = left.m2 + right.m2;
|
||||||
result.m3 = left.m3 + right.m3;
|
result.m3 = left.m3 + right.m3;
|
||||||
result.m4 = left.m4 + right.m4;
|
result.m4 = left.m4 + right.m4;
|
||||||
result.m5 = left.m5 + right.m5;
|
result.m5 = left.m5 + right.m5;
|
||||||
result.m6 = left.m6 + right.m6;
|
result.m6 = left.m6 + right.m6;
|
||||||
result.m7 = left.m7 + right.m7;
|
result.m7 = left.m7 + right.m7;
|
||||||
result.m8 = left.m8 + right.m8;
|
result.m8 = left.m8 + right.m8;
|
||||||
result.m9 = left.m9 + right.m9;
|
result.m9 = left.m9 + right.m9;
|
||||||
result.m10 = left.m10 + right.m10;
|
result.m10 = left.m10 + right.m10;
|
||||||
result.m11 = left.m11 + right.m11;
|
result.m11 = left.m11 + right.m11;
|
||||||
result.m12 = left.m12 + right.m12;
|
result.m12 = left.m12 + right.m12;
|
||||||
result.m13 = left.m13 + right.m13;
|
result.m13 = left.m13 + right.m13;
|
||||||
result.m14 = left.m14 + right.m14;
|
result.m14 = left.m14 + right.m14;
|
||||||
result.m15 = left.m15 + right.m15;
|
result.m15 = left.m15 + right.m15;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -393,21 +415,21 @@ Matrix MatrixSubstract(Matrix left, Matrix right)
|
||||||
Matrix result = MatrixIdentity();
|
Matrix result = MatrixIdentity();
|
||||||
|
|
||||||
result.m0 = left.m0 - right.m0;
|
result.m0 = left.m0 - right.m0;
|
||||||
result.m1 = left.m1 - right.m1;
|
result.m1 = left.m1 - right.m1;
|
||||||
result.m2 = left.m2 - right.m2;
|
result.m2 = left.m2 - right.m2;
|
||||||
result.m3 = left.m3 - right.m3;
|
result.m3 = left.m3 - right.m3;
|
||||||
result.m4 = left.m4 - right.m4;
|
result.m4 = left.m4 - right.m4;
|
||||||
result.m5 = left.m5 - right.m5;
|
result.m5 = left.m5 - right.m5;
|
||||||
result.m6 = left.m6 - right.m6;
|
result.m6 = left.m6 - right.m6;
|
||||||
result.m7 = left.m7 - right.m7;
|
result.m7 = left.m7 - right.m7;
|
||||||
result.m8 = left.m8 - right.m8;
|
result.m8 = left.m8 - right.m8;
|
||||||
result.m9 = left.m9 - right.m9;
|
result.m9 = left.m9 - right.m9;
|
||||||
result.m10 = left.m10 - right.m10;
|
result.m10 = left.m10 - right.m10;
|
||||||
result.m11 = left.m11 - right.m11;
|
result.m11 = left.m11 - right.m11;
|
||||||
result.m12 = left.m12 - right.m12;
|
result.m12 = left.m12 - right.m12;
|
||||||
result.m13 = left.m13 - right.m13;
|
result.m13 = left.m13 - right.m13;
|
||||||
result.m14 = left.m14 - right.m14;
|
result.m14 = left.m14 - right.m14;
|
||||||
result.m15 = left.m15 - right.m15;
|
result.m15 = left.m15 - right.m15;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -476,51 +498,51 @@ Matrix MatrixFromAxisAngle(Vector3 axis, float angle)
|
||||||
|
|
||||||
Matrix mat = MatrixIdentity();
|
Matrix mat = MatrixIdentity();
|
||||||
|
|
||||||
float x = axis.x, y = axis.y, z = axis.z;
|
float x = axis.x, y = axis.y, z = axis.z;
|
||||||
|
|
||||||
float length = sqrt(x*x + y*y + z*z);
|
float length = sqrt(x*x + y*y + z*z);
|
||||||
|
|
||||||
if ((length != 1) && (length != 0))
|
if ((length != 1) && (length != 0))
|
||||||
{
|
{
|
||||||
length = 1 / length;
|
length = 1 / length;
|
||||||
x *= length;
|
x *= length;
|
||||||
y *= length;
|
y *= length;
|
||||||
z *= 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;
|
|
||||||
result.m2 = a02*b00 + a12*b01 + a22*b02;
|
|
||||||
result.m3 = a03*b00 + a13*b01 + a23*b02;
|
|
||||||
result.m4 = a00*b10 + a10*b11 + a20*b12;
|
|
||||||
result.m5 = a01*b10 + a11*b11 + a21*b12;
|
|
||||||
result.m6 = a02*b10 + a12*b11 + a22*b12;
|
|
||||||
result.m7 = a03*b10 + a13*b11 + a23*b12;
|
|
||||||
result.m8 = a00*b20 + a10*b21 + a20*b22;
|
|
||||||
result.m9 = a01*b20 + a11*b21 + a21*b22;
|
|
||||||
result.m10 = a02*b20 + a12*b21 + a22*b22;
|
|
||||||
result.m11 = a03*b20 + a13*b21 + a23*b22;
|
|
||||||
result.m12 = mat.m12;
|
|
||||||
result.m13 = mat.m13;
|
|
||||||
result.m14 = mat.m14;
|
|
||||||
result.m15 = mat.m15;
|
|
||||||
|
|
||||||
return result;
|
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;
|
||||||
|
result.m2 = a02*b00 + a12*b01 + a22*b02;
|
||||||
|
result.m3 = a03*b00 + a13*b01 + a23*b02;
|
||||||
|
result.m4 = a00*b10 + a10*b11 + a20*b12;
|
||||||
|
result.m5 = a01*b10 + a11*b11 + a21*b12;
|
||||||
|
result.m6 = a02*b10 + a12*b11 + a22*b12;
|
||||||
|
result.m7 = a03*b10 + a13*b11 + a23*b12;
|
||||||
|
result.m8 = a00*b20 + a10*b21 + a20*b22;
|
||||||
|
result.m9 = a01*b20 + a11*b21 + a21*b22;
|
||||||
|
result.m10 = a02*b20 + a12*b21 + a22*b22;
|
||||||
|
result.m11 = a03*b20 + a13*b21 + a23*b22;
|
||||||
|
result.m12 = mat.m12;
|
||||||
|
result.m13 = mat.m13;
|
||||||
|
result.m14 = mat.m14;
|
||||||
|
result.m15 = mat.m15;
|
||||||
|
|
||||||
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Create rotation matrix from axis and angle
|
// Create rotation matrix from axis and angle
|
||||||
|
@ -645,35 +667,35 @@ Matrix MatrixMultiply(Matrix left, Matrix right)
|
||||||
{
|
{
|
||||||
Matrix result;
|
Matrix result;
|
||||||
|
|
||||||
// Cache the matrix values (speed optimization)
|
// Cache the matrix values (speed optimization)
|
||||||
float a00 = left.m0, a01 = left.m1, a02 = left.m2, a03 = left.m3;
|
float a00 = left.m0, a01 = left.m1, a02 = left.m2, a03 = left.m3;
|
||||||
float a10 = left.m4, a11 = left.m5, a12 = left.m6, a13 = left.m7;
|
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 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 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 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 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 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;
|
float b30 = right.m12, b31 = right.m13, b32 = right.m14, b33 = right.m15;
|
||||||
|
|
||||||
result.m0 = b00*a00 + b01*a10 + b02*a20 + b03*a30;
|
result.m0 = b00*a00 + b01*a10 + b02*a20 + b03*a30;
|
||||||
result.m1 = b00*a01 + b01*a11 + b02*a21 + b03*a31;
|
result.m1 = b00*a01 + b01*a11 + b02*a21 + b03*a31;
|
||||||
result.m2 = b00*a02 + b01*a12 + b02*a22 + b03*a32;
|
result.m2 = b00*a02 + b01*a12 + b02*a22 + b03*a32;
|
||||||
result.m3 = b00*a03 + b01*a13 + b02*a23 + b03*a33;
|
result.m3 = b00*a03 + b01*a13 + b02*a23 + b03*a33;
|
||||||
result.m4 = b10*a00 + b11*a10 + b12*a20 + b13*a30;
|
result.m4 = b10*a00 + b11*a10 + b12*a20 + b13*a30;
|
||||||
result.m5 = b10*a01 + b11*a11 + b12*a21 + b13*a31;
|
result.m5 = b10*a01 + b11*a11 + b12*a21 + b13*a31;
|
||||||
result.m6 = b10*a02 + b11*a12 + b12*a22 + b13*a32;
|
result.m6 = b10*a02 + b11*a12 + b12*a22 + b13*a32;
|
||||||
result.m7 = b10*a03 + b11*a13 + b12*a23 + b13*a33;
|
result.m7 = b10*a03 + b11*a13 + b12*a23 + b13*a33;
|
||||||
result.m8 = b20*a00 + b21*a10 + b22*a20 + b23*a30;
|
result.m8 = b20*a00 + b21*a10 + b22*a20 + b23*a30;
|
||||||
result.m9 = b20*a01 + b21*a11 + b22*a21 + b23*a31;
|
result.m9 = b20*a01 + b21*a11 + b22*a21 + b23*a31;
|
||||||
result.m10 = b20*a02 + b21*a12 + b22*a22 + b23*a32;
|
result.m10 = b20*a02 + b21*a12 + b22*a22 + b23*a32;
|
||||||
result.m11 = b20*a03 + b21*a13 + b22*a23 + b23*a33;
|
result.m11 = b20*a03 + b21*a13 + b22*a23 + b23*a33;
|
||||||
result.m12 = b30*a00 + b31*a10 + b32*a20 + b33*a30;
|
result.m12 = b30*a00 + b31*a10 + b32*a20 + b33*a30;
|
||||||
result.m13 = b30*a01 + b31*a11 + b32*a21 + b33*a31;
|
result.m13 = b30*a01 + b31*a11 + b32*a21 + b33*a31;
|
||||||
result.m14 = b30*a02 + b31*a12 + b32*a22 + b33*a32;
|
result.m14 = b30*a02 + b31*a12 + b32*a22 + b33*a32;
|
||||||
result.m15 = b30*a03 + b31*a13 + b32*a23 + b33*a33;
|
result.m15 = b30*a03 + b31*a13 + b32*a23 + b33*a33;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns perspective projection matrix
|
// Returns perspective projection matrix
|
||||||
|
@ -681,28 +703,28 @@ Matrix MatrixFrustum(double left, double right, double bottom, double top, doubl
|
||||||
{
|
{
|
||||||
Matrix result;
|
Matrix result;
|
||||||
|
|
||||||
float rl = (right - left);
|
float rl = (right - left);
|
||||||
float tb = (top - bottom);
|
float tb = (top - bottom);
|
||||||
float fn = (far - near);
|
float fn = (far - near);
|
||||||
|
|
||||||
result.m0 = (near*2) / rl;
|
result.m0 = (near*2) / rl;
|
||||||
result.m1 = 0;
|
result.m1 = 0;
|
||||||
result.m2 = 0;
|
result.m2 = 0;
|
||||||
result.m3 = 0;
|
result.m3 = 0;
|
||||||
result.m4 = 0;
|
result.m4 = 0;
|
||||||
result.m5 = (near*2) / tb;
|
result.m5 = (near*2) / tb;
|
||||||
result.m6 = 0;
|
result.m6 = 0;
|
||||||
result.m7 = 0;
|
result.m7 = 0;
|
||||||
result.m8 = (right + left) / rl;
|
result.m8 = (right + left) / rl;
|
||||||
result.m9 = (top + bottom) / tb;
|
result.m9 = (top + bottom) / tb;
|
||||||
result.m10 = -(far + near) / fn;
|
result.m10 = -(far + near) / fn;
|
||||||
result.m11 = -1;
|
result.m11 = -1;
|
||||||
result.m12 = 0;
|
result.m12 = 0;
|
||||||
result.m13 = 0;
|
result.m13 = 0;
|
||||||
result.m14 = -(far*near*2) / fn;
|
result.m14 = -(far*near*2) / fn;
|
||||||
result.m15 = 0;
|
result.m15 = 0;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns perspective projection matrix
|
// Returns perspective projection matrix
|
||||||
|
@ -720,25 +742,25 @@ Matrix MatrixOrtho(double left, double right, double bottom, double top, double
|
||||||
Matrix result;
|
Matrix result;
|
||||||
|
|
||||||
float rl = (right - left);
|
float rl = (right - left);
|
||||||
float tb = (top - bottom);
|
float tb = (top - bottom);
|
||||||
float fn = (far - near);
|
float fn = (far - near);
|
||||||
|
|
||||||
result.m0 = 2 / rl;
|
result.m0 = 2 / rl;
|
||||||
result.m1 = 0;
|
result.m1 = 0;
|
||||||
result.m2 = 0;
|
result.m2 = 0;
|
||||||
result.m3 = 0;
|
result.m3 = 0;
|
||||||
result.m4 = 0;
|
result.m4 = 0;
|
||||||
result.m5 = 2 / tb;
|
result.m5 = 2 / tb;
|
||||||
result.m6 = 0;
|
result.m6 = 0;
|
||||||
result.m7 = 0;
|
result.m7 = 0;
|
||||||
result.m8 = 0;
|
result.m8 = 0;
|
||||||
result.m9 = 0;
|
result.m9 = 0;
|
||||||
result.m10 = -2 / fn;
|
result.m10 = -2 / fn;
|
||||||
result.m11 = 0;
|
result.m11 = 0;
|
||||||
result.m12 = -(left + right) / rl;
|
result.m12 = -(left + right) / rl;
|
||||||
result.m13 = -(top + bottom) / tb;
|
result.m13 = -(top + bottom) / tb;
|
||||||
result.m14 = -(far + near) / fn;
|
result.m14 = -(far + near) / fn;
|
||||||
result.m15 = 1;
|
result.m15 = 1;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -747,7 +769,7 @@ Matrix MatrixOrtho(double left, double right, double bottom, double top, double
|
||||||
Matrix MatrixLookAt(Vector3 eye, Vector3 target, Vector3 up)
|
Matrix MatrixLookAt(Vector3 eye, Vector3 target, Vector3 up)
|
||||||
{
|
{
|
||||||
Matrix result;
|
Matrix result;
|
||||||
|
|
||||||
Vector3 z = VectorSubtract(eye, target);
|
Vector3 z = VectorSubtract(eye, target);
|
||||||
VectorNormalize(&z);
|
VectorNormalize(&z);
|
||||||
Vector3 x = VectorCrossProduct(up, z);
|
Vector3 x = VectorCrossProduct(up, z);
|
||||||
|
@ -793,7 +815,7 @@ void PrintMatrix(Matrix m)
|
||||||
// Calculates the length of a quaternion
|
// Calculates the length of a quaternion
|
||||||
float QuaternionLength(Quaternion quat)
|
float QuaternionLength(Quaternion quat)
|
||||||
{
|
{
|
||||||
return sqrt(quat.x*quat.x + quat.y*quat.y + quat.z*quat.z + quat.w*quat.w);
|
return sqrt(quat.x*quat.x + quat.y*quat.y + quat.z*quat.z + quat.w*quat.w);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Normalize provided quaternion
|
// Normalize provided quaternion
|
||||||
|
@ -818,15 +840,15 @@ Quaternion QuaternionMultiply(Quaternion q1, Quaternion q2)
|
||||||
{
|
{
|
||||||
Quaternion result;
|
Quaternion result;
|
||||||
|
|
||||||
float qax = q1.x, qay = q1.y, qaz = q1.z, qaw = q1.w;
|
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;
|
float qbx = q2.x, qby = q2.y, qbz = q2.z, qbw = q2.w;
|
||||||
|
|
||||||
result.x = qax*qbw + qaw*qbx + qay*qbz - qaz*qby;
|
result.x = qax*qbw + qaw*qbx + qay*qbz - qaz*qby;
|
||||||
result.y = qay*qbw + qaw*qby + qaz*qbx - qax*qbz;
|
result.y = qay*qbw + qaw*qby + qaz*qbx - qax*qbz;
|
||||||
result.z = qaz*qbw + qaw*qbz + qax*qby - qay*qbx;
|
result.z = qaz*qbw + qaw*qbz + qax*qby - qay*qbx;
|
||||||
result.w = qaw*qbw - qax*qbx - qay*qby - qaz*qbz;
|
result.w = qaw*qbw - qax*qbx - qay*qby - qaz*qbz;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculates spherical linear interpolation between two quaternions
|
// Calculates spherical linear interpolation between two quaternions
|
||||||
|
@ -834,9 +856,9 @@ Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float amount)
|
||||||
{
|
{
|
||||||
Quaternion result;
|
Quaternion result;
|
||||||
|
|
||||||
float cosHalfTheta = q1.x*q2.x + q1.y*q2.y + q1.z*q2.z + q1.w*q2.w;
|
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;
|
if (abs(cosHalfTheta) >= 1.0) result = q1;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
float halfTheta = acos(cosHalfTheta);
|
float halfTheta = acos(cosHalfTheta);
|
||||||
|
@ -859,9 +881,9 @@ Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float amount)
|
||||||
result.z = (q1.z*ratioA + q2.z*ratioB);
|
result.z = (q1.z*ratioA + q2.z*ratioB);
|
||||||
result.w = (q1.w*ratioA + q2.w*ratioB);
|
result.w = (q1.w*ratioA + q2.w*ratioB);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a quaternion from a given rotation matrix
|
// Returns a quaternion from a given rotation matrix
|
||||||
|
@ -947,42 +969,42 @@ Matrix QuaternionToMatrix(Quaternion q)
|
||||||
{
|
{
|
||||||
Matrix result;
|
Matrix result;
|
||||||
|
|
||||||
float x = q.x, y = q.y, z = q.z, w = q.w;
|
float x = q.x, y = q.y, z = q.z, w = q.w;
|
||||||
|
|
||||||
float x2 = x + x;
|
float x2 = x + x;
|
||||||
float y2 = y + y;
|
float y2 = y + y;
|
||||||
float z2 = z + z;
|
float z2 = z + z;
|
||||||
|
|
||||||
float xx = x*x2;
|
float xx = x*x2;
|
||||||
float xy = x*y2;
|
float xy = x*y2;
|
||||||
float xz = x*z2;
|
float xz = x*z2;
|
||||||
|
|
||||||
float yy = y*y2;
|
float yy = y*y2;
|
||||||
float yz = y*z2;
|
float yz = y*z2;
|
||||||
float zz = z*z2;
|
float zz = z*z2;
|
||||||
|
|
||||||
float wx = w*x2;
|
float wx = w*x2;
|
||||||
float wy = w*y2;
|
float wy = w*y2;
|
||||||
float wz = w*z2;
|
float wz = w*z2;
|
||||||
|
|
||||||
result.m0 = 1 - (yy + zz);
|
result.m0 = 1 - (yy + zz);
|
||||||
result.m1 = xy - wz;
|
result.m1 = xy - wz;
|
||||||
result.m2 = xz + wy;
|
result.m2 = xz + wy;
|
||||||
result.m3 = 0;
|
result.m3 = 0;
|
||||||
result.m4 = xy + wz;
|
result.m4 = xy + wz;
|
||||||
result.m5 = 1 - (xx + zz);
|
result.m5 = 1 - (xx + zz);
|
||||||
result.m6 = yz - wx;
|
result.m6 = yz - wx;
|
||||||
result.m7 = 0;
|
result.m7 = 0;
|
||||||
result.m8 = xz - wy;
|
result.m8 = xz - wy;
|
||||||
result.m9 = yz + wx;
|
result.m9 = yz + wx;
|
||||||
result.m10 = 1 - (xx + yy);
|
result.m10 = 1 - (xx + yy);
|
||||||
result.m11 = 0;
|
result.m11 = 0;
|
||||||
result.m12 = 0;
|
result.m12 = 0;
|
||||||
result.m13 = 0;
|
result.m13 = 0;
|
||||||
result.m14 = 0;
|
result.m14 = 0;
|
||||||
result.m15 = 1;
|
result.m15 = 1;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the axis and the angle for a given quaternion
|
// Returns the axis and the angle for a given quaternion
|
||||||
|
|
|
@ -91,6 +91,8 @@ void VectorNormalize(Vector3 *v); // Normalize provided ve
|
||||||
float VectorDistance(Vector3 v1, Vector3 v2); // Calculate distance between two points
|
float VectorDistance(Vector3 v1, Vector3 v2); // Calculate distance between two points
|
||||||
Vector3 VectorLerp(Vector3 v1, Vector3 v2, float amount); // Calculate linear interpolation between two vectors
|
Vector3 VectorLerp(Vector3 v1, Vector3 v2, float amount); // Calculate linear interpolation between two vectors
|
||||||
Vector3 VectorReflect(Vector3 vector, Vector3 normal); // Calculate reflected vector to normal
|
Vector3 VectorReflect(Vector3 vector, Vector3 normal); // Calculate reflected vector to normal
|
||||||
|
void VectorTransform(Vector3 *v, Matrix mat); // Transforms a Vector3 with a given Matrix
|
||||||
|
Vector3 VectorZero(); // Return a Vector3 init to zero
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
// Functions Declaration to work with Matrix
|
// Functions Declaration to work with Matrix
|
||||||
|
|
1572
src/rlgl.c
Normal file
1572
src/rlgl.c
Normal file
File diff suppressed because it is too large
Load diff
153
src/rlgl.h
Normal file
153
src/rlgl.h
Normal file
|
@ -0,0 +1,153 @@
|
||||||
|
/*********************************************************************************************
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
* 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
|
||||||
|
* 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
|
||||||
|
* 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
|
||||||
|
* as being the original software.
|
||||||
|
*
|
||||||
|
* 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*
|
||||||
|
**********************************************************************************************/
|
||||||
|
|
||||||
|
#ifndef RLGL_H
|
||||||
|
#define RLGL_H
|
||||||
|
|
||||||
|
//#define RLGL_STANDALONE // NOTE: To use rlgl as standalone lib, just uncomment this line
|
||||||
|
|
||||||
|
#ifndef RLGL_STANDALONE
|
||||||
|
#include "raylib.h" // Required for typedef: Model
|
||||||
|
#include "utils.h" // Required for function TraceLog()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "raymath.h" // Required for data type Matrix and Matrix functions
|
||||||
|
|
||||||
|
// Select desired OpenGL version
|
||||||
|
//#define USE_OPENGL_11
|
||||||
|
#define USE_OPENGL_33
|
||||||
|
//#define USE_OPENGL_ES2
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Defines and Macros
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
#define MAX_LINES_BATCH 8192 // 1024
|
||||||
|
#define MAX_TRIANGLES_BATCH 2048
|
||||||
|
#define MAX_QUADS_BATCH 8192
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Types and Structures Definition
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
typedef unsigned char byte;
|
||||||
|
|
||||||
|
typedef enum { RL_PROJECTION, RL_MODELVIEW, RL_TEXTURE } MatrixMode;
|
||||||
|
|
||||||
|
typedef enum { RL_LINES, RL_TRIANGLES, RL_QUADS } DrawMode;
|
||||||
|
|
||||||
|
#ifdef RLGL_STANDALONE
|
||||||
|
typedef struct Model Model;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int numVertices;
|
||||||
|
float *vertices; // 3 components per vertex
|
||||||
|
float *texcoords; // 2 components per vertex
|
||||||
|
float *normals; // 3 components per vertex
|
||||||
|
} VertexData;
|
||||||
|
|
||||||
|
#ifdef USE_OPENGL_11
|
||||||
|
struct Model {
|
||||||
|
VertexData data;
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
struct Model {
|
||||||
|
unsigned int vaoId;
|
||||||
|
Matrix transform;
|
||||||
|
int numVertices;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" { // Prevents name mangling of functions
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
// Functions Declaration - Matrix operations
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
void rlMatrixMode(int mode); // Choose the current matrix to be transformed
|
||||||
|
void rlPushMatrix(); // TODO: REVIEW: Required? - Push the current matrix to stack
|
||||||
|
void rlPopMatrix(); // TODO: REVIEW: Required? - Pop lattest inserted matrix from stack
|
||||||
|
void rlLoadIdentity(); // Reset current matrix to identity matrix
|
||||||
|
void rlTranslatef(float x, float y, float z); // Multiply the current matrix by a translation matrix
|
||||||
|
void rlRotatef(float angleDeg, float x, float y, float z); // Multiply the current matrix by a rotation matrix
|
||||||
|
void rlScalef(float x, float y, float z); // Multiply the current matrix by a scaling matrix
|
||||||
|
void rlMultMatrixf(float *mat); // Multiply the current matrix by another matrix
|
||||||
|
void rlFrustum(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);
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
// Functions Declaration - Vertex level operations
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
void rlBegin(int mode); // Initialize drawing mode (how to organize vertex)
|
||||||
|
void rlEnd(); // Finish vertex providing
|
||||||
|
void rlVertex2i(int x, int y); // Define one vertex (position) - 2 int
|
||||||
|
void rlVertex2f(float x, float y); // Define one vertex (position) - 2 float
|
||||||
|
void rlVertex3f(float x, float y, float z); // Define one vertex (position) - 3 float
|
||||||
|
void rlTexCoord2f(float x, float y); // Define one vertex (texture coordinate) - 2 float
|
||||||
|
void rlNormal3f(float x, float y, float z); // Define one vertex (normal) - 3 float
|
||||||
|
void rlColor4ub(byte r, byte g, byte b, byte a); // Define one vertex (color) - 4 byte
|
||||||
|
void rlColor3f(float x, float y, float z); // Define one vertex (color) - 3 float
|
||||||
|
void rlColor4f(float x, float y, float z, float w); // Define one vertex (color) - 4 float
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
// Functions Declaration - OpenGL equivalent functions (common to 1.1, 3.3+, ES2)
|
||||||
|
// NOTE: This functions are used to completely abstract raylib code from OpenGL layer
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
void rlEnableTexture(unsigned int id); // Enable texture usage
|
||||||
|
void rlDisableTexture(); // Disable texture usage
|
||||||
|
void rlDeleteTextures(unsigned int id); // Delete OpenGL texture from GPU
|
||||||
|
void rlDeleteVertexArrays(unsigned int id); // Unload vertex data from GPU memory
|
||||||
|
void rlClearColor(byte r, byte g, byte b, byte a); // Clear color buffer with color
|
||||||
|
void rlClearScreenBuffers(); // Clear used screen buffers (color and depth)
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
// Functions Declaration - rlgl functionality
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
#if defined(USE_OPENGL_33) || defined(USE_OPENGL_ES2)
|
||||||
|
void rlglInit(); // Initialize rlgl (shaders, VAO, VBO...)
|
||||||
|
void rlglClose(); // De-init rlgl
|
||||||
|
void rlglDraw(); // Draw VAOs
|
||||||
|
unsigned int rlglLoadModel(VertexData data);
|
||||||
|
unsigned int rlglLoadCompressedTexture(unsigned char *data, int width, int height, int mipmapCount, int format);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void rlglDrawModel(Model model, Vector3 position, float scale, bool wires); // Draw model
|
||||||
|
void rlglInitGraphicsDevice(int fbWidth, int fbHeight); // Initialize Graphics Device (OpenGL stuff)
|
||||||
|
unsigned int rlglLoadTexture(int width, int height, unsigned char *pixels); // Load in GPU OpenGL texture
|
||||||
|
byte *rlglReadScreenPixels(int width, int height); // Read screen pixel data (color buffer)
|
||||||
|
|
||||||
|
#if defined(USE_OPENGL_33) || defined(USE_OPENGL_ES2)
|
||||||
|
void PrintProjectionMatrix(); // DEBUG: Print projection matrix
|
||||||
|
void PrintModelviewMatrix(); // DEBUG: Print modelview matrix
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // RLGL_H
|
304
src/shapes.c
304
src/shapes.c
|
@ -25,10 +25,11 @@
|
||||||
|
|
||||||
#include "raylib.h"
|
#include "raylib.h"
|
||||||
|
|
||||||
#include <GL/gl.h> // OpenGL functions
|
|
||||||
#include <stdlib.h> // Required for abs() function
|
#include <stdlib.h> // Required for abs() function
|
||||||
#include <math.h> // Math related functions, sin() and cos() used on DrawCircle*
|
#include <math.h> // Math related functions, sin() and cos() used on DrawCircle*
|
||||||
// sqrt() and pow() and abs() used on CheckCollision*
|
// sqrt() and pow() and abs() used on CheckCollision*
|
||||||
|
|
||||||
|
#include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3+ or ES2
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Defines and Macros
|
// Defines and Macros
|
||||||
|
@ -57,149 +58,108 @@
|
||||||
// Draw a pixel
|
// Draw a pixel
|
||||||
void DrawPixel(int posX, int posY, Color color)
|
void DrawPixel(int posX, int posY, Color color)
|
||||||
{
|
{
|
||||||
glBegin(GL_POINTS);
|
rlBegin(RL_LINES);
|
||||||
glColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
glVertex2i(posX, posY);
|
rlVertex2i(posX, posY);
|
||||||
glEnd();
|
rlVertex2i(posX + 1, posY + 1);
|
||||||
|
rlEnd();
|
||||||
// NOTE1: Alternative method to draw a pixel (GL_LINES)
|
|
||||||
/*
|
|
||||||
glBegin(GL_LINES);
|
|
||||||
glColor4ub(color.r, color.g, color.b, color.a);
|
|
||||||
glVertex2i(posX, posY);
|
|
||||||
glVertex2i(posX+1, posY+1);
|
|
||||||
glEnd();
|
|
||||||
*/
|
|
||||||
// NOTE2: Alternative method to draw a pixel (glPoint())
|
|
||||||
/*
|
|
||||||
glEnable(GL_POINT_SMOOTH);
|
|
||||||
glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); // Deprecated on OGL 3.0
|
|
||||||
|
|
||||||
glPointSize(1.0f);
|
|
||||||
glPoint((float)posX, (float)posY, 0.0f);
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw a pixel (Vector version)
|
// Draw a pixel (Vector version)
|
||||||
void DrawPixelV(Vector2 position, Color color)
|
void DrawPixelV(Vector2 position, Color color)
|
||||||
{
|
{
|
||||||
glBegin(GL_POINTS);
|
rlBegin(RL_LINES);
|
||||||
glColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
glVertex2f(position.x, position.y);
|
rlVertex2f(position.x, position.y);
|
||||||
glEnd();
|
rlVertex2i(position.x + 1, position.y + 1);
|
||||||
|
rlEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw a line
|
// Draw a line
|
||||||
void DrawLine(int startPosX, int startPosY, int endPosX, int endPosY, Color color)
|
void DrawLine(int startPosX, int startPosY, int endPosX, int endPosY, Color color)
|
||||||
{
|
{
|
||||||
glBegin(GL_LINES);
|
rlBegin(RL_LINES);
|
||||||
glColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
glVertex2i(startPosX, startPosY);
|
rlVertex2i(startPosX, startPosY);
|
||||||
glVertex2i(endPosX, endPosY);
|
rlVertex2i(endPosX, endPosY);
|
||||||
glEnd();
|
rlEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw a line (Vector version)
|
// Draw a line (Vector version)
|
||||||
void DrawLineV(Vector2 startPos, Vector2 endPos, Color color)
|
void DrawLineV(Vector2 startPos, Vector2 endPos, Color color)
|
||||||
{
|
{
|
||||||
glBegin(GL_LINES);
|
rlBegin(RL_LINES);
|
||||||
glColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
glVertex2f(startPos.x, startPos.y);
|
rlVertex2f(startPos.x, startPos.y);
|
||||||
glVertex2f(endPos.x, endPos.y);
|
rlVertex2f(endPos.x, endPos.y);
|
||||||
glEnd();
|
rlEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw a color-filled circle
|
// Draw a color-filled circle
|
||||||
// TODO: Review, on some GPUs is drawn with a weird transparency (GL_POLYGON_SMOOTH issue?)
|
|
||||||
void DrawCircle(int centerX, int centerY, float radius, Color color)
|
void DrawCircle(int centerX, int centerY, float radius, Color color)
|
||||||
{
|
{
|
||||||
glEnable(GL_POLYGON_SMOOTH);
|
|
||||||
glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); // Deprecated on OGL 3.0
|
|
||||||
|
|
||||||
DrawPoly((Vector2){centerX, centerY}, 360, radius, 0, color);
|
DrawPoly((Vector2){centerX, centerY}, 360, radius, 0, color);
|
||||||
|
|
||||||
glDisable(GL_POLYGON_SMOOTH);
|
|
||||||
|
|
||||||
// NOTE: Alternative method to draw a circle (point)
|
|
||||||
/*
|
|
||||||
glEnable(GL_POINT_SMOOTH);
|
|
||||||
glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); // Deprecated on OGL 3.0
|
|
||||||
|
|
||||||
glPointSize(radius);
|
|
||||||
glPoint((float)centerX, (float)centerY, 0.0f);
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw a gradient-filled circle
|
// Draw a gradient-filled circle
|
||||||
// NOTE: Gradient goes from center (color1) to border (color2)
|
// NOTE: Gradient goes from center (color1) to border (color2)
|
||||||
void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Color color2)
|
void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Color color2)
|
||||||
{
|
{
|
||||||
glBegin(GL_TRIANGLE_FAN);
|
rlBegin(RL_TRIANGLES);
|
||||||
glColor4ub(color1.r, color1.g, color1.b, color1.a);
|
for (int i=0; i < 360; i += 2)
|
||||||
glVertex2i(centerX, centerY);
|
|
||||||
glColor4ub(color2.r, color2.g, color2.b, color2.a);
|
|
||||||
|
|
||||||
for (int i=0; i <= 360; i++) //i++ --> Step = 1.0 pixels
|
|
||||||
{
|
{
|
||||||
glVertex2f(centerX + sin(DEG2RAD*i) * radius, centerY + cos(DEG2RAD*i) * radius);
|
rlColor4ub(color1.r, color1.g, color1.b, color1.a);
|
||||||
|
rlVertex2i(centerX, centerY);
|
||||||
|
rlColor4ub(color2.r, color2.g, color2.b, color2.a);
|
||||||
|
rlVertex2f(centerX + sin(DEG2RAD*i) * radius, centerY + cos(DEG2RAD*i) * radius);
|
||||||
|
rlVertex2f(centerX + sin(DEG2RAD*(i+2)) * radius, centerY + cos(DEG2RAD*(i+2)) * radius);
|
||||||
}
|
}
|
||||||
glEnd();
|
rlEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw a color-filled circle (Vector version)
|
// Draw a color-filled circle (Vector version)
|
||||||
void DrawCircleV(Vector2 center, float radius, Color color)
|
void DrawCircleV(Vector2 center, float radius, Color color)
|
||||||
{
|
{
|
||||||
glEnable(GL_POLYGON_SMOOTH);
|
rlBegin(RL_TRIANGLES);
|
||||||
glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
|
for (int i=0; i < 360; i += 2)
|
||||||
|
|
||||||
glBegin(GL_TRIANGLE_FAN);
|
|
||||||
glColor4ub(color.r, color.g, color.b, color.a);
|
|
||||||
glVertex2f(center.x, center.y);
|
|
||||||
|
|
||||||
for (int i=0; i <= 360; i++) //i++ --> Step = 1.0 pixels
|
|
||||||
{
|
{
|
||||||
glVertex2f(center.x + sin(DEG2RAD*i) * radius, center.y + cos(DEG2RAD*i) * radius);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
rlVertex2i(center.x, center.y);
|
||||||
|
rlVertex2f(center.x + sin(DEG2RAD*i) * radius, center.y + cos(DEG2RAD*i) * radius);
|
||||||
|
rlVertex2f(center.x + sin(DEG2RAD*(i+2)) * radius, center.y + cos(DEG2RAD*(i+2)) * radius);
|
||||||
}
|
}
|
||||||
glEnd();
|
rlEnd();
|
||||||
|
|
||||||
glDisable(GL_POLYGON_SMOOTH);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw circle outline
|
// Draw circle outline
|
||||||
void DrawCircleLines(int centerX, int centerY, float radius, Color color)
|
void DrawCircleLines(int centerX, int centerY, float radius, Color color)
|
||||||
{
|
{
|
||||||
glEnable(GL_LINE_SMOOTH); // Smoothies circle outline (anti-aliasing applied)
|
rlBegin(RL_LINES);
|
||||||
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); // Best quality for line smooth (anti-aliasing best algorithm)
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
|
||||||
glBegin(GL_LINE_LOOP);
|
|
||||||
glColor4ub(color.r, color.g, color.b, color.a);
|
|
||||||
|
|
||||||
// NOTE: Circle outline is drawn pixel by pixel every degree (0 to 360)
|
// NOTE: Circle outline is drawn pixel by pixel every degree (0 to 360)
|
||||||
for (int i=0; i < 360; i++)
|
for (int i=0; i < 360; i++)
|
||||||
{
|
{
|
||||||
glVertex2f(centerX + sin(DEG2RAD*i) * radius, centerY + cos(DEG2RAD*i) * radius);
|
rlVertex2f(centerX + sin(DEG2RAD*i) * radius, centerY + cos(DEG2RAD*i) * radius);
|
||||||
|
rlVertex2f(centerX + sin(DEG2RAD*(i+1)) * radius, centerY + cos(DEG2RAD*(i+1)) * radius);
|
||||||
}
|
}
|
||||||
glEnd();
|
rlEnd();
|
||||||
|
|
||||||
// NOTE: Alternative method to draw circle outline
|
|
||||||
/*
|
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
|
||||||
DrawCircle(centerX, centerY, radius, color);
|
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
||||||
*/
|
|
||||||
glDisable(GL_LINE_SMOOTH);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw a color-filled rectangle
|
// Draw a color-filled rectangle
|
||||||
void DrawRectangle(int posX, int posY, int width, int height, Color color)
|
void DrawRectangle(int posX, int posY, int width, int height, Color color)
|
||||||
{
|
{
|
||||||
glBegin(GL_QUADS);
|
rlBegin(RL_QUADS);
|
||||||
glColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
glVertex2i(posX, posY);
|
rlTexCoord2f(0.0f, 0.0f);
|
||||||
glVertex2i(posX + width, posY);
|
rlVertex2i(posX, posY);
|
||||||
glVertex2i(posX + width, posY + height);
|
rlTexCoord2f(0.0f, 1.0f);
|
||||||
glVertex2i(posX, posY + height);
|
rlVertex2i(posX, posY + height);
|
||||||
glEnd();
|
rlTexCoord2f(1.0f, 1.0f);
|
||||||
|
rlVertex2i(posX + width, posY + height);
|
||||||
|
rlTexCoord2f(1.0f, 0.0f);
|
||||||
|
rlVertex2i(posX + width, posY);
|
||||||
|
rlEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw a color-filled rectangle
|
// Draw a color-filled rectangle
|
||||||
|
@ -212,73 +172,73 @@ void DrawRectangleRec(Rectangle rec, Color color)
|
||||||
// NOTE: Gradient goes from bottom (color1) to top (color2)
|
// NOTE: Gradient goes from bottom (color1) to top (color2)
|
||||||
void DrawRectangleGradient(int posX, int posY, int width, int height, Color color1, Color color2)
|
void DrawRectangleGradient(int posX, int posY, int width, int height, Color color1, Color color2)
|
||||||
{
|
{
|
||||||
glBegin(GL_QUADS);
|
rlBegin(RL_QUADS);
|
||||||
glColor4ub(color1.r, color1.g, color1.b, color1.a);
|
rlColor4ub(color1.r, color1.g, color1.b, color1.a);
|
||||||
glVertex2i(posX, posY);
|
rlVertex2i(posX, posY);
|
||||||
glVertex2i(posX + width, posY);
|
rlColor4ub(color1.r, color1.g, color1.b, color1.a);
|
||||||
glColor4ub(color2.r, color2.g, color2.b, color2.a);
|
rlVertex2i(posX, posY + height);
|
||||||
glVertex2i(posX + width, posY + height);
|
rlColor4ub(color2.r, color2.g, color2.b, color2.a);
|
||||||
glVertex2i(posX, posY + height);
|
rlVertex2i(posX + width, posY + height);
|
||||||
glEnd();
|
rlColor4ub(color2.r, color2.g, color2.b, color2.a);
|
||||||
|
rlVertex2i(posX + width, posY);
|
||||||
|
rlEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw a color-filled rectangle (Vector version)
|
// Draw a color-filled rectangle (Vector version)
|
||||||
void DrawRectangleV(Vector2 position, Vector2 size, Color color)
|
void DrawRectangleV(Vector2 position, Vector2 size, Color color)
|
||||||
{
|
{
|
||||||
glBegin(GL_QUADS);
|
rlBegin(RL_QUADS);
|
||||||
glColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
glVertex2i(position.x, position.y);
|
rlVertex2i(position.x, position.y);
|
||||||
glVertex2i(position.x + size.x, position.y);
|
rlVertex2i(position.x, position.y + size.y);
|
||||||
glVertex2i(position.x + size.x, position.y + size.y);
|
rlVertex2i(position.x + size.x, position.y + size.y);
|
||||||
glVertex2i(position.x, position.y + size.y);
|
rlVertex2i(position.x + size.x, position.y);
|
||||||
glEnd();
|
rlEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw rectangle outline
|
// Draw rectangle outline
|
||||||
void DrawRectangleLines(int posX, int posY, int width, int height, Color color)
|
void DrawRectangleLines(int posX, int posY, int width, int height, Color color)
|
||||||
{
|
{
|
||||||
//glEnable(GL_LINE_SMOOTH); // Smoothies circle outline (anti-aliasing applied)
|
rlBegin(RL_LINES);
|
||||||
//glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); // Best quality for line smooth (anti-aliasing best algorithm)
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
rlVertex2i(posX, posY);
|
||||||
// NOTE: Lines are rasterized using the "Diamond Exit" rule so, it's nearly impossible to obtain a pixel-perfect engine
|
rlVertex2i(posX + width - 1, posY);
|
||||||
// NOTE: Recommended trying to avoid using lines, at least >1.0f pixel lines with anti-aliasing (glLineWidth function)
|
|
||||||
|
rlVertex2i(posX + width - 1, posY);
|
||||||
glBegin(GL_LINE_LOOP);
|
rlVertex2i(posX + width - 1, posY + height - 1);
|
||||||
glColor4ub(color.r, color.g, color.b, color.a);
|
|
||||||
glVertex2i(posX, posY);
|
rlVertex2i(posX + width - 1, posY + height - 1);
|
||||||
glVertex2i(posX + width - 1, posY);
|
rlVertex2i(posX, posY + height - 1);
|
||||||
glVertex2i(posX + width - 1, posY + height - 1);
|
|
||||||
glVertex2i(posX, posY + height - 1);
|
rlVertex2i(posX, posY + height - 1);
|
||||||
glEnd();
|
rlVertex2i(posX, posY);
|
||||||
|
rlEnd();
|
||||||
// NOTE: Alternative method to draw rectangle outline
|
|
||||||
/*
|
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
|
||||||
DrawRectangle(posX, posY, width - 1, height - 1, color);
|
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
||||||
*/
|
|
||||||
//glDisable(GL_LINE_SMOOTH);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw a triangle
|
// Draw a triangle
|
||||||
void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color)
|
void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color)
|
||||||
{
|
{
|
||||||
glBegin(GL_TRIANGLES);
|
rlBegin(RL_TRIANGLES);
|
||||||
glColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
glVertex2f(v1.x, v1.y);
|
rlVertex2f(v1.x, v1.y);
|
||||||
glVertex2f(v2.x, v2.y);
|
rlVertex2f(v2.x, v2.y);
|
||||||
glVertex2f(v3.x, v3.y);
|
rlVertex2f(v3.x, v3.y);
|
||||||
glEnd();
|
rlEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color)
|
void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color)
|
||||||
{
|
{
|
||||||
glBegin(GL_LINE_LOOP);
|
rlBegin(RL_LINES);
|
||||||
glColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
glVertex2f(v1.x, v1.y);
|
rlVertex2f(v1.x, v1.y);
|
||||||
glVertex2f(v2.x, v2.y);
|
rlVertex2f(v2.x, v2.y);
|
||||||
glVertex2f(v3.x, v3.y);
|
|
||||||
glEnd();
|
rlVertex2f(v2.x, v2.y);
|
||||||
|
rlVertex2f(v3.x, v3.y);
|
||||||
|
|
||||||
|
rlVertex2f(v3.x, v3.y);
|
||||||
|
rlVertex2f(v1.x, v1.y);
|
||||||
|
rlEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw a regular polygon of n sides (Vector version)
|
// Draw a regular polygon of n sides (Vector version)
|
||||||
|
@ -286,20 +246,21 @@ void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color col
|
||||||
{
|
{
|
||||||
if (sides < 3) sides = 3;
|
if (sides < 3) sides = 3;
|
||||||
|
|
||||||
glPushMatrix();
|
rlPushMatrix();
|
||||||
glTranslatef(center.x, center.y, 0);
|
rlTranslatef(center.x, center.y, 0.0);
|
||||||
glRotatef(rotation, 0, 0, 1);
|
rlRotatef(rotation, 0, 0, 1);
|
||||||
|
|
||||||
glBegin(GL_TRIANGLE_FAN);
|
rlBegin(RL_TRIANGLES);
|
||||||
glColor4ub(color.r, color.g, color.b, color.a);
|
for (int i=0; i < 360; i += 360/sides)
|
||||||
glVertex2f(0, 0);
|
{
|
||||||
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
for (int i=0; i <= sides; i++)
|
|
||||||
{
|
rlVertex2i(0, 0);
|
||||||
glVertex2f(radius*cos(i*2*PI/sides), radius*sin(i*2*PI/sides));
|
rlVertex2f(sin(DEG2RAD*i) * radius, cos(DEG2RAD*i) * radius);
|
||||||
|
rlVertex2f(sin(DEG2RAD*(i+360/sides)) * radius, cos(DEG2RAD*(i+360/sides)) * radius);
|
||||||
}
|
}
|
||||||
glEnd();
|
rlEnd();
|
||||||
glPopMatrix();
|
rlPopMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw a closed polygon defined by points
|
// Draw a closed polygon defined by points
|
||||||
|
@ -308,19 +269,16 @@ void DrawPolyEx(Vector2 *points, int numPoints, Color color)
|
||||||
{
|
{
|
||||||
if (numPoints >= 3)
|
if (numPoints >= 3)
|
||||||
{
|
{
|
||||||
glEnable(GL_POLYGON_SMOOTH);
|
rlBegin(RL_TRIANGLES);
|
||||||
glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
|
||||||
glBegin(GL_POLYGON);
|
|
||||||
glColor4ub(color.r, color.g, color.b, color.a);
|
|
||||||
|
|
||||||
for (int i = 0; i < numPoints; i++)
|
for (int i = 0; i < numPoints - 2; i++)
|
||||||
{
|
{
|
||||||
glVertex2f(points[i].x, points[i].y);
|
rlVertex2f(points[i].x, points[i].y);
|
||||||
|
rlVertex2f(points[i+1].x, points[i+1].y);
|
||||||
|
rlVertex2f(points[i+2].x, points[i+2].y);
|
||||||
}
|
}
|
||||||
glEnd();
|
rlEnd();
|
||||||
|
|
||||||
glDisable(GL_POLYGON_SMOOTH);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -330,22 +288,22 @@ void DrawPolyExLines(Vector2 *points, int numPoints, Color color)
|
||||||
{
|
{
|
||||||
if (numPoints >= 2)
|
if (numPoints >= 2)
|
||||||
{
|
{
|
||||||
//glEnable(GL_LINE_SMOOTH); // Smoothies circle outline (anti-aliasing applied)
|
rlBegin(RL_LINES);
|
||||||
//glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); // Best quality for line smooth (anti-aliasing best algorithm)
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
|
||||||
glBegin(GL_LINE_LOOP);
|
|
||||||
glColor4ub(color.r, color.g, color.b, color.a);
|
|
||||||
|
|
||||||
for (int i = 0; i < numPoints; i++)
|
for (int i = 0; i < numPoints - 1; i++)
|
||||||
{
|
{
|
||||||
glVertex2f(points[i].x, points[i].y);
|
rlVertex2f(points[i].x, points[i].y);
|
||||||
|
rlVertex2f(points[i+1].x, points[i+1].y);
|
||||||
}
|
}
|
||||||
glEnd();
|
rlEnd();
|
||||||
|
|
||||||
//glDisable(GL_LINE_SMOOTH);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Module Functions Definition - Collision Detection functions
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Check if point is inside rectangle
|
// Check if point is inside rectangle
|
||||||
bool CheckCollisionPointRec(Vector2 point, Rectangle rec)
|
bool CheckCollisionPointRec(Vector2 point, Rectangle rec)
|
||||||
{
|
{
|
||||||
|
|
|
@ -11,5 +11,4 @@ void main()
|
||||||
{
|
{
|
||||||
// Output pixel color
|
// Output pixel color
|
||||||
pixelColor = texture(texture0, fragTexCoord) * fragColor;
|
pixelColor = texture(texture0, fragTexCoord) * fragColor;
|
||||||
//pixelColor = fragColor;
|
|
||||||
}
|
}
|
|
@ -11,6 +11,7 @@
|
||||||
// Get the latest version and other information at:
|
// Get the latest version and other information at:
|
||||||
// http://nothings.org/stb_vorbis/
|
// http://nothings.org/stb_vorbis/
|
||||||
|
|
||||||
|
|
||||||
// Todo:
|
// Todo:
|
||||||
//
|
//
|
||||||
// - seeking (note you can seek yourself using the pushdata API)
|
// - seeking (note you can seek yourself using the pushdata API)
|
||||||
|
@ -25,6 +26,9 @@
|
||||||
//
|
//
|
||||||
// All of these limitations may be removed in future versions.
|
// All of these limitations may be removed in future versions.
|
||||||
|
|
||||||
|
|
||||||
|
#include "stb_vorbis.h"
|
||||||
|
|
||||||
#ifndef STB_VORBIS_HEADER_ONLY
|
#ifndef STB_VORBIS_HEADER_ONLY
|
||||||
|
|
||||||
// global configuration settings (e.g. set these in the project/makefile),
|
// global configuration settings (e.g. set these in the project/makefile),
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
// Get the latest version and other information at:
|
// Get the latest version and other information at:
|
||||||
// http://nothings.org/stb_vorbis/
|
// http://nothings.org/stb_vorbis/
|
||||||
|
|
||||||
|
|
||||||
// Todo:
|
// Todo:
|
||||||
//
|
//
|
||||||
// - seeking (note you can seek yourself using the pushdata API)
|
// - seeking (note you can seek yourself using the pushdata API)
|
||||||
|
@ -25,12 +26,6 @@
|
||||||
//
|
//
|
||||||
// All of these limitations may be removed in future versions.
|
// All of these limitations may be removed in future versions.
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// HEADER BEGINS HERE
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef STB_VORBIS_INCLUDE_STB_VORBIS_H
|
#ifndef STB_VORBIS_INCLUDE_STB_VORBIS_H
|
||||||
#define STB_VORBIS_INCLUDE_STB_VORBIS_H
|
#define STB_VORBIS_INCLUDE_STB_VORBIS_H
|
||||||
|
|
||||||
|
@ -349,4 +344,4 @@ enum STBVorbisError
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // STB_VORBIS_INCLUDE_STB_VORBIS_H
|
#endif // STB_VORBIS_INCLUDE_STB_VORBIS_H
|
187
src/text.c
187
src/text.c
|
@ -28,12 +28,13 @@
|
||||||
|
|
||||||
#include "raylib.h"
|
#include "raylib.h"
|
||||||
|
|
||||||
#include <GL/gl.h> // OpenGL functions
|
|
||||||
#include <stdlib.h> // Declares malloc() and free() for memory management
|
#include <stdlib.h> // Declares malloc() and free() for memory management
|
||||||
#include <string.h> // String management functions (just strlen() is used)
|
#include <string.h> // String management functions (just strlen() is used)
|
||||||
#include <stdarg.h> // Used for functions with variable number of parameters (FormatText())
|
#include <stdarg.h> // Used for functions with variable number of parameters (FormatText())
|
||||||
#include "stb_image.h" // Used to read image data (multiple formats support)
|
#include "stb_image.h" // Used to read image data (multiple formats support)
|
||||||
|
|
||||||
|
#include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3+ or ES2
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Defines and Macros
|
// Defines and Macros
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
@ -49,13 +50,22 @@
|
||||||
typedef unsigned char byte;
|
typedef unsigned char byte;
|
||||||
|
|
||||||
// SpriteFont one Character (Glyph) data
|
// SpriteFont one Character (Glyph) data
|
||||||
struct Character {
|
typedef struct Character {
|
||||||
int value; //char value = ' '; (int)value = 32;
|
int value; //char value = ' '; (int)value = 32;
|
||||||
int x;
|
int x;
|
||||||
int y;
|
int y;
|
||||||
int w;
|
int w;
|
||||||
int h;
|
int h;
|
||||||
|
} Character;
|
||||||
|
|
||||||
|
// SpriteFont type, includes texture and charSet array data
|
||||||
|
/*
|
||||||
|
struct SpriteFont {
|
||||||
|
Texture2D texture;
|
||||||
|
int numChars;
|
||||||
|
Character *charSet;
|
||||||
};
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Global variables
|
// Global variables
|
||||||
|
@ -63,6 +73,11 @@ struct Character {
|
||||||
static SpriteFont defaultFont; // Default font provided by raylib
|
static SpriteFont defaultFont; // Default font provided by raylib
|
||||||
// NOTE: defaultFont is loaded on InitWindow and disposed on CloseWindow [module: core]
|
// NOTE: defaultFont is loaded on InitWindow and disposed on CloseWindow [module: core]
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Other Modules Functions Declaration (required by text)
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
//...
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module specific Functions Declaration
|
// Module specific Functions Declaration
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
@ -78,9 +93,11 @@ static const char *GetExtension(const char *fileName);
|
||||||
extern void LoadDefaultFont()
|
extern void LoadDefaultFont()
|
||||||
{
|
{
|
||||||
defaultFont.numChars = 96; // We know our default font has 94 chars
|
defaultFont.numChars = 96; // We know our default font has 94 chars
|
||||||
defaultFont.texture.width = 128; // We know our default font texture is 128 pixels width
|
|
||||||
defaultFont.texture.height = 64; // We know our default font texture is 64 pixels height
|
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)
|
// Default font is directly defined here (data generated from a sprite font image)
|
||||||
// This way, we reconstruct SpriteFont without creating large global variables
|
// 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
|
// This data is automatically allocated to Stack and automatically deallocated at the end of this function
|
||||||
|
@ -115,7 +132,31 @@ extern void LoadDefaultFont()
|
||||||
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 };
|
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)
|
||||||
|
{
|
||||||
|
for (int j = 31; j >= 0; j--)
|
||||||
|
{
|
||||||
|
if (BIT_CHECK(defaultFontData[counter], j)) image.pixels[i+j] = WHITE;
|
||||||
|
}
|
||||||
|
|
||||||
|
counter++;
|
||||||
|
|
||||||
|
if (counter > 256) counter = 0; // Security check...
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultFont.texture = CreateTexture(image); // Convert loaded image to OpenGL texture
|
||||||
|
|
||||||
|
UnloadImage(image);
|
||||||
|
|
||||||
// Reconstruct charSet using charsWidth[], charsHeight, charsDivisor, numChars
|
// Reconstruct charSet using charsWidth[], charsHeight, charsDivisor, numChars
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
defaultFont.charSet = (Character *)malloc(defaultFont.numChars * sizeof(Character)); // Allocate space for our character data
|
defaultFont.charSet = (Character *)malloc(defaultFont.numChars * sizeof(Character)); // Allocate space for our character data
|
||||||
|
@ -146,52 +187,12 @@ extern void LoadDefaultFont()
|
||||||
else currentPosX = testPosX;
|
else currentPosX = testPosX;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Re-construct image from defaultFontData and generate OpenGL texture
|
TraceLog(INFO, "Default font loaded successfully");
|
||||||
//----------------------------------------------------------------------
|
|
||||||
Color *imgDataPixel = (Color *)malloc(defaultFont.texture.width * defaultFont.texture.height * sizeof(Color));
|
|
||||||
|
|
||||||
for (int i = 0; i < defaultFont.texture.width * defaultFont.texture.height; i++) imgDataPixel[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 < defaultFont.texture.width * defaultFont.texture.height; i += 32)
|
|
||||||
{
|
|
||||||
for (int j = 31; j >= 0; j--)
|
|
||||||
{
|
|
||||||
if (BIT_CHECK(defaultFontData[counter], j)) imgDataPixel[i+j] = WHITE;
|
|
||||||
}
|
|
||||||
|
|
||||||
counter++;
|
|
||||||
|
|
||||||
if (counter > 256) counter = 0; // Security check...
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert loaded data to OpenGL texture
|
|
||||||
//----------------------------------------
|
|
||||||
GLuint id;
|
|
||||||
glGenTextures(1, &id); // Generate pointer to the texture
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, id);
|
|
||||||
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); // Set texture to clamp on x-axis
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); // Set texture to clamp on y-axis
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_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
|
|
||||||
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, defaultFont.texture.width, defaultFont.texture.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imgDataPixel);
|
|
||||||
|
|
||||||
// NOTE: Not using mipmappings (texture for 2D drawing)
|
|
||||||
// At this point we have the image converted to texture and uploaded to GPU
|
|
||||||
|
|
||||||
free(imgDataPixel); // Now we can free loaded data from RAM memory
|
|
||||||
|
|
||||||
defaultFont.texture.glId = id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void UnloadDefaultFont()
|
extern void UnloadDefaultFont()
|
||||||
{
|
{
|
||||||
glDeleteTextures(1, &defaultFont.texture.glId);
|
rlDeleteTextures(defaultFont.texture.glId);
|
||||||
free(defaultFont.charSet);
|
free(defaultFont.charSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,6 +207,8 @@ SpriteFont LoadSpriteFont(const char* fileName)
|
||||||
{
|
{
|
||||||
SpriteFont spriteFont;
|
SpriteFont spriteFont;
|
||||||
|
|
||||||
|
Image image;
|
||||||
|
|
||||||
// Check file extension
|
// Check file extension
|
||||||
if (strcmp(GetExtension(fileName),"rbmf") == 0) spriteFont = LoadRBMF(fileName);
|
if (strcmp(GetExtension(fileName),"rbmf") == 0) spriteFont = LoadRBMF(fileName);
|
||||||
else
|
else
|
||||||
|
@ -240,8 +243,8 @@ SpriteFont LoadSpriteFont(const char* fileName)
|
||||||
// spriteFont.charSet data is filled inside the function and memory is allocated!
|
// spriteFont.charSet data is filled inside the function and memory is allocated!
|
||||||
int numChars = ParseImageData(imgDataPixel, imgWidth, imgHeight, &spriteFont.charSet);
|
int numChars = ParseImageData(imgDataPixel, imgWidth, imgHeight, &spriteFont.charSet);
|
||||||
|
|
||||||
fprintf(stderr, "SpriteFont data parsed correctly!\n");
|
TraceLog(INFO, "[%s] SpriteFont data parsed correctly", fileName);
|
||||||
fprintf(stderr, "SpriteFont num chars: %i\n", numChars);
|
TraceLog(INFO, "[%s] SpriteFont num chars detected: %i", numChars);
|
||||||
|
|
||||||
spriteFont.numChars = numChars;
|
spriteFont.numChars = numChars;
|
||||||
|
|
||||||
|
@ -265,29 +268,18 @@ SpriteFont LoadSpriteFont(const char* fileName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stderr, "SpriteFont texture converted to POT: %i %i\n", potWidth, potHeight);
|
TraceLog(WARNING, "SpriteFont texture converted to POT: %ix%i", potWidth, potHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(imgDataPixel);
|
free(imgDataPixel);
|
||||||
|
|
||||||
// Convert loaded data to OpenGL texture
|
image.pixels = imgDataPixelPOT;
|
||||||
//----------------------------------------
|
image.width = potWidth;
|
||||||
GLuint id;
|
image.height = potHeight;
|
||||||
glGenTextures(1, &id); // Generate pointer to the texture
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, id);
|
spriteFont.texture = CreateTexture(image); // Convert loaded image to OpenGL texture
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_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
|
UnloadImage(image);
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, potWidth, potHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, imgDataPixelPOT);
|
|
||||||
|
|
||||||
// NOTE: Not using mipmappings (texture for 2D drawing)
|
|
||||||
// At this point we have the image converted to texture and uploaded to GPU
|
|
||||||
|
|
||||||
free(imgDataPixelPOT); // Now we can free loaded data from RAM memory
|
|
||||||
|
|
||||||
spriteFont.texture.glId = id;
|
|
||||||
spriteFont.texture.width = potWidth;
|
|
||||||
spriteFont.texture.height = potHeight;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return spriteFont;
|
return spriteFont;
|
||||||
|
@ -296,7 +288,7 @@ SpriteFont LoadSpriteFont(const char* fileName)
|
||||||
// Unload SpriteFont from GPU memory
|
// Unload SpriteFont from GPU memory
|
||||||
void UnloadSpriteFont(SpriteFont spriteFont)
|
void UnloadSpriteFont(SpriteFont spriteFont)
|
||||||
{
|
{
|
||||||
glDeleteTextures(1, &spriteFont.texture.glId);
|
rlDeleteTextures(spriteFont.texture.glId);
|
||||||
free(spriteFont.charSet);
|
free(spriteFont.charSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -330,28 +322,33 @@ void DrawTextEx(SpriteFont spriteFont, const char* text, Vector2 position, int f
|
||||||
if (fontSize <= spriteFont.charSet[0].h) scaleFactor = 1.0f;
|
if (fontSize <= spriteFont.charSet[0].h) scaleFactor = 1.0f;
|
||||||
else scaleFactor = (float)fontSize / spriteFont.charSet[0].h;
|
else scaleFactor = (float)fontSize / spriteFont.charSet[0].h;
|
||||||
|
|
||||||
glEnable(GL_TEXTURE_2D);
|
rlEnableTexture(spriteFont.texture.glId);
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, spriteFont.texture.glId);
|
rlBegin(RL_QUADS);
|
||||||
|
|
||||||
// Optimized to use one draw call per string
|
|
||||||
glBegin(GL_QUADS);
|
|
||||||
for(int i = 0; i < length; i++)
|
for(int i = 0; i < length; i++)
|
||||||
{
|
{
|
||||||
c = spriteFont.charSet[(int)text[i] - FONT_FIRST_CHAR];
|
c = spriteFont.charSet[(int)text[i] - FONT_FIRST_CHAR];
|
||||||
|
|
||||||
glColor4ub(tint.r, tint.g, tint.b, tint.a);
|
rlColor4ub(tint.r, tint.g, tint.b, tint.a);
|
||||||
glNormal3f(0.0f, 0.0f, 1.0f); // Normal Pointing Towards Viewer
|
rlNormal3f(0.0f, 0.0f, 1.0f); // Normal Pointing Towards Viewer
|
||||||
glTexCoord2f((float)c.x / spriteFont.texture.width, (float)c.y / spriteFont.texture.height); glVertex2f(positionX, position.y);
|
|
||||||
glTexCoord2f((float)c.x / spriteFont.texture.width, (float)(c.y + c.h) / spriteFont.texture.height); glVertex2f(positionX, position.y + (c.h) * scaleFactor);
|
rlTexCoord2f((float)c.x / spriteFont.texture.width, (float)c.y / spriteFont.texture.height);
|
||||||
glTexCoord2f((float)(c.x + c.w) / spriteFont.texture.width, (float)(c.y + c.h) / spriteFont.texture.height); glVertex2f(positionX + (c.w) * scaleFactor, position.y + (c.h) * scaleFactor);
|
rlVertex2f(positionX, position.y);
|
||||||
glTexCoord2f((float)(c.x + c.w) / spriteFont.texture.width, (float)c.y / spriteFont.texture.height); glVertex2f(positionX + (c.w) * scaleFactor, position.y);
|
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
rlVertex2f(positionX + (c.w) * scaleFactor, position.y);
|
||||||
|
|
||||||
positionX += ((spriteFont.charSet[(int)text[i] - FONT_FIRST_CHAR].w) * scaleFactor + spacing);
|
positionX += ((spriteFont.charSet[(int)text[i] - FONT_FIRST_CHAR].w) * scaleFactor + spacing);
|
||||||
}
|
}
|
||||||
glEnd();
|
rlEnd();
|
||||||
|
|
||||||
glDisable(GL_TEXTURE_2D);
|
rlDisableTexture();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Formatting of text with variables to 'embed'
|
// Formatting of text with variables to 'embed'
|
||||||
|
@ -361,7 +358,7 @@ const char *FormatText(const char *text, ...)
|
||||||
|
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, text);
|
va_start(args, text);
|
||||||
vsprintf(buffer, text, args); // NOTE: We use vsprintf() defined in <stdarg.h>
|
vsprintf(buffer, text, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
|
@ -417,21 +414,18 @@ void DrawFPS(int posX, int posY)
|
||||||
char buffer[20];
|
char buffer[20];
|
||||||
|
|
||||||
if (counter < refreshRate)
|
if (counter < refreshRate)
|
||||||
{
|
{
|
||||||
sprintf(buffer, "%2.0f FPS", fps);
|
|
||||||
DrawText(buffer, posX, posY, 20, LIME);
|
|
||||||
|
|
||||||
counter++;
|
counter++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fps = GetFPS();
|
fps = GetFPS();
|
||||||
refreshRate = fps;
|
refreshRate = fps;
|
||||||
sprintf(buffer, "%2.0f FPS", fps);
|
|
||||||
DrawText(buffer, posX, posY, 20, LIME);
|
|
||||||
|
|
||||||
counter = 0;
|
counter = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sprintf(buffer, "%2.0f FPS", fps);
|
||||||
|
DrawText(buffer, posX, posY, 20, LIME);
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
@ -564,7 +558,7 @@ static SpriteFont LoadRBMF(const char *fileName)
|
||||||
|
|
||||||
fread(&rbmfHeader, sizeof(rbmfInfoHeader), 1, rbmfFile);
|
fread(&rbmfHeader, sizeof(rbmfInfoHeader), 1, rbmfFile);
|
||||||
|
|
||||||
//printf("rBMF info: %i %i %i %i\n", rbmfHeader.imgWidth, rbmfHeader.imgHeight, rbmfHeader.numChars, rbmfHeader.charHeight);
|
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;
|
spriteFont.numChars = (int)rbmfHeader.numChars;
|
||||||
|
|
||||||
|
@ -581,8 +575,6 @@ static SpriteFont LoadRBMF(const char *fileName)
|
||||||
|
|
||||||
for(int i = 0; i < spriteFont.numChars; i++) fread(&rbmfCharWidthData[i], sizeof(unsigned char), 1, rbmfFile);
|
for(int i = 0; i < spriteFont.numChars; i++) fread(&rbmfCharWidthData[i], sizeof(unsigned char), 1, rbmfFile);
|
||||||
|
|
||||||
printf("Just read image data and width data... Starting image reconstruction...");
|
|
||||||
|
|
||||||
// Re-construct image from rbmfFileData
|
// Re-construct image from rbmfFileData
|
||||||
//-----------------------------------------
|
//-----------------------------------------
|
||||||
image.pixels = (Color *)malloc(image.width * image.height * sizeof(Color));
|
image.pixels = (Color *)malloc(image.width * image.height * sizeof(Color));
|
||||||
|
@ -602,13 +594,13 @@ static SpriteFont LoadRBMF(const char *fileName)
|
||||||
counter++;
|
counter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Image reconstructed correctly... now converting it to texture...");
|
TraceLog(INFO, "[%s] Image reconstructed correctly, now converting it to texture", fileName);
|
||||||
|
|
||||||
spriteFont.texture = CreateTexture(image);
|
spriteFont.texture = CreateTexture(image);
|
||||||
|
|
||||||
UnloadImage(image); // Unload image data
|
UnloadImage(image); // Unload image data
|
||||||
|
|
||||||
printf("Starting charSet reconstruction...\n");
|
TraceLog(INFO, "[%s] Starting charSet reconstruction", fileName);
|
||||||
|
|
||||||
// Reconstruct charSet using rbmfCharWidthData, rbmfHeader.charHeight, charsDivisor, rbmfHeader.numChars
|
// Reconstruct charSet using rbmfCharWidthData, rbmfHeader.charHeight, charsDivisor, rbmfHeader.numChars
|
||||||
spriteFont.charSet = (Character *)malloc(spriteFont.numChars * sizeof(Character)); // Allocate space for our character data
|
spriteFont.charSet = (Character *)malloc(spriteFont.numChars * sizeof(Character)); // Allocate space for our character data
|
||||||
|
@ -637,11 +629,9 @@ static SpriteFont LoadRBMF(const char *fileName)
|
||||||
spriteFont.charSet[i].y = charsDivisor + currentLine * (rbmfHeader.charHeight + charsDivisor);
|
spriteFont.charSet[i].y = charsDivisor + currentLine * (rbmfHeader.charHeight + charsDivisor);
|
||||||
}
|
}
|
||||||
else currentPosX = testPosX;
|
else currentPosX = testPosX;
|
||||||
|
|
||||||
//printf("Char %i data: %i %i %i %i\n", spriteFont.charSet[i].value, spriteFont.charSet[i].x, spriteFont.charSet[i].y, spriteFont.charSet[i].w, spriteFont.charSet[i].h);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("CharSet reconstructed correctly... Data should be ready...\n");
|
TraceLog(INFO, "[%s] rBMF file loaded correctly as SpriteFont", fileName);
|
||||||
|
|
||||||
fclose(rbmfFile);
|
fclose(rbmfFile);
|
||||||
|
|
||||||
|
@ -651,6 +641,7 @@ static SpriteFont LoadRBMF(const char *fileName)
|
||||||
return spriteFont;
|
return spriteFont;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the extension for a filename
|
||||||
static const char *GetExtension(const char *fileName)
|
static const char *GetExtension(const char *fileName)
|
||||||
{
|
{
|
||||||
const char *dot = strrchr(fileName, '.');
|
const char *dot = strrchr(fileName, '.');
|
||||||
|
|
605
src/textures.c
605
src/textures.c
|
@ -28,12 +28,13 @@
|
||||||
|
|
||||||
#include "raylib.h"
|
#include "raylib.h"
|
||||||
|
|
||||||
#include <GL/gl.h> // OpenGL functions
|
|
||||||
#include <stdlib.h> // Declares malloc() and free() for memory management
|
#include <stdlib.h> // Declares malloc() and free() for memory management
|
||||||
|
#include <string.h> // Required for strcmp(), strrchr(), strncmp()
|
||||||
#include "stb_image.h" // Used to read image data (multiple formats support)
|
#include "stb_image.h" // Used to read image data (multiple formats support)
|
||||||
|
|
||||||
#include "utils.h" // rRES data decompression utility function
|
#include "utils.h" // rRES data decompression utility function
|
||||||
|
|
||||||
|
#include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3+ or ES2
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Defines and Macros
|
// Defines and Macros
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
@ -44,15 +45,29 @@
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
typedef unsigned char byte;
|
typedef unsigned char byte;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned char *data;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
int mipmaps;
|
||||||
|
int format;
|
||||||
|
} ImageDDS;
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Global Variables Definition
|
// Global Variables Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// It's lonely here...
|
// It's lonely here...
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Other Modules Functions Declaration (required by text)
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
//...
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module specific Functions Declaration
|
// Module specific Functions Declaration
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// No private (static) functions in this module (.c file)
|
static const char *GetExtension(const char *fileName);
|
||||||
|
static ImageDDS LoadDDS(const char *fileName);
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module Functions Definition
|
// Module Functions Definition
|
||||||
|
@ -63,32 +78,44 @@ Image LoadImage(const char *fileName)
|
||||||
{
|
{
|
||||||
Image image;
|
Image image;
|
||||||
|
|
||||||
int imgWidth;
|
if ((strcmp(GetExtension(fileName),"png") == 0) ||
|
||||||
int imgHeight;
|
(strcmp(GetExtension(fileName),"bmp") == 0) ||
|
||||||
int imgBpp;
|
(strcmp(GetExtension(fileName),"tga") == 0) ||
|
||||||
|
(strcmp(GetExtension(fileName),"jpg") == 0) ||
|
||||||
// NOTE: Using stb_image to load images (Supports: BMP, TGA, PNG, JPG, ...)
|
(strcmp(GetExtension(fileName),"gif") == 0) ||
|
||||||
// Force loading to 4 components (RGBA)
|
(strcmp(GetExtension(fileName),"psd") == 0) ||
|
||||||
byte *imgData = stbi_load(fileName, &imgWidth, &imgHeight, &imgBpp, 4);
|
(strcmp(GetExtension(fileName),"pic") == 0))
|
||||||
|
{
|
||||||
// Convert array to pixel array for working convenience
|
int imgWidth;
|
||||||
image.pixels = (Color *)malloc(imgWidth * imgHeight * sizeof(Color));
|
int imgHeight;
|
||||||
|
int imgBpp;
|
||||||
int pix = 0;
|
|
||||||
|
// NOTE: Using stb_image to load images (Supports: BMP, TGA, PNG, JPG, ...)
|
||||||
for (int i = 0; i < (imgWidth * imgHeight * 4); i += 4)
|
// Force loading to 4 components (RGBA)
|
||||||
{
|
byte *imgData = stbi_load(fileName, &imgWidth, &imgHeight, &imgBpp, 4);
|
||||||
image.pixels[pix].r = imgData[i];
|
|
||||||
image.pixels[pix].g = imgData[i+1];
|
// Convert array to pixel array for working convenience
|
||||||
image.pixels[pix].b = imgData[i+2];
|
image.pixels = (Color *)malloc(imgWidth * imgHeight * sizeof(Color));
|
||||||
image.pixels[pix].a = imgData[i+3];
|
|
||||||
pix++;
|
int pix = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < (imgWidth * imgHeight * 4); i += 4)
|
||||||
|
{
|
||||||
|
image.pixels[pix].r = imgData[i];
|
||||||
|
image.pixels[pix].g = imgData[i+1];
|
||||||
|
image.pixels[pix].b = imgData[i+2];
|
||||||
|
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 extension not recognized, it can't be loaded", fileName);
|
||||||
stbi_image_free(imgData);
|
|
||||||
|
|
||||||
image.width = imgWidth;
|
|
||||||
image.height = imgHeight;
|
|
||||||
|
|
||||||
// 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.
|
// to do that struct data alignment should be the right one (4 byte); it is.
|
||||||
|
@ -113,103 +140,104 @@ Image LoadImageFromRES(const char *rresName, int resId)
|
||||||
|
|
||||||
FILE *rresFile = fopen(rresName, "rb");
|
FILE *rresFile = fopen(rresName, "rb");
|
||||||
|
|
||||||
if (!rresFile) printf("Error opening raylib Resource file\n");
|
if (!rresFile) TraceLog(WARNING, "[%s] Could not open raylib resource file", rresName);
|
||||||
|
else
|
||||||
// Read rres file (basic file check - id)
|
|
||||||
fread(&id[0], sizeof(char), 1, rresFile);
|
|
||||||
fread(&id[1], sizeof(char), 1, rresFile);
|
|
||||||
fread(&id[2], sizeof(char), 1, rresFile);
|
|
||||||
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'))
|
|
||||||
{
|
{
|
||||||
printf("This is not a valid raylib Resource file!\n");
|
// Read rres file (basic file check - id)
|
||||||
exit(1);
|
fread(&id[0], sizeof(char), 1, rresFile);
|
||||||
}
|
fread(&id[1], sizeof(char), 1, rresFile);
|
||||||
|
fread(&id[2], sizeof(char), 1, rresFile);
|
||||||
// Read number of resources embedded
|
fread(&id[3], sizeof(char), 1, rresFile);
|
||||||
fread(&numRes, sizeof(short), 1, rresFile);
|
fread(&version, sizeof(char), 1, rresFile);
|
||||||
|
fread(&useless, sizeof(char), 1, rresFile);
|
||||||
for (int i = 0; i < numRes; i++)
|
|
||||||
{
|
|
||||||
fread(&infoHeader, sizeof(ResInfoHeader), 1, rresFile);
|
|
||||||
|
|
||||||
if (infoHeader.id == resId)
|
if ((id[0] != 'r') && (id[1] != 'R') && (id[2] != 'E') &&(id[3] != 'S'))
|
||||||
{
|
{
|
||||||
found = true;
|
TraceLog(WARNING, "[%s] This is not a valid raylib resource file", rresName);
|
||||||
|
|
||||||
// Check data is of valid IMAGE type
|
|
||||||
if (infoHeader.type == 0) // IMAGE data type
|
|
||||||
{
|
|
||||||
// TODO: Check data compression type
|
|
||||||
|
|
||||||
// NOTE: We suppose compression type 2 (DEFLATE - default)
|
|
||||||
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)
|
|
||||||
|
|
||||||
printf("Image width: %i\n", (int)imgWidth);
|
|
||||||
printf("Image height: %i\n", (int)imgHeight);
|
|
||||||
|
|
||||||
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];
|
|
||||||
image.pixels[pix].g = imgData[i+1];
|
|
||||||
image.pixels[pix].b = imgData[i+2];
|
|
||||||
image.pixels[pix].a = imgData[i+3];
|
|
||||||
pix++;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(imgData);
|
|
||||||
|
|
||||||
free(data);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf("Required resource do not seem to be a valid IMAGE resource\n");
|
|
||||||
exit(2);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Depending on type, skip the right amount of parameters
|
// Read number of resources embedded
|
||||||
switch (infoHeader.type)
|
fread(&numRes, sizeof(short), 1, rresFile);
|
||||||
{
|
|
||||||
case 0: fseek(rresFile, 6, SEEK_CUR); break; // IMAGE: Jump 6 bytes of parameters
|
|
||||||
case 1: fseek(rresFile, 6, SEEK_CUR); break; // SOUND: Jump 6 bytes of parameters
|
|
||||||
case 2: fseek(rresFile, 5, SEEK_CUR); break; // MODEL: Jump 5 bytes of parameters (TODO: Review)
|
|
||||||
case 3: break; // TEXT: No parameters
|
|
||||||
case 4: break; // RAW: No parameters
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Jump DATA to read next infoHeader
|
for (int i = 0; i < numRes; i++)
|
||||||
fseek(rresFile, infoHeader.size, SEEK_CUR);
|
{
|
||||||
}
|
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
|
||||||
|
{
|
||||||
|
// TODO: Check data compression type
|
||||||
|
|
||||||
|
// NOTE: We suppose compression type 2 (DEFLATE - default)
|
||||||
|
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];
|
||||||
|
image.pixels[pix].g = imgData[i+1];
|
||||||
|
image.pixels[pix].b = imgData[i+2];
|
||||||
|
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
|
||||||
|
{
|
||||||
|
TraceLog(WARNING, "[%s] Required resource do not seem to be a valid IMAGE resource", rresName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Depending on type, skip the right amount of parameters
|
||||||
|
switch (infoHeader.type)
|
||||||
|
{
|
||||||
|
case 0: fseek(rresFile, 6, SEEK_CUR); break; // IMAGE: Jump 6 bytes of parameters
|
||||||
|
case 1: fseek(rresFile, 6, SEEK_CUR); break; // SOUND: Jump 6 bytes of parameters
|
||||||
|
case 2: fseek(rresFile, 5, SEEK_CUR); break; // MODEL: Jump 5 bytes of parameters (TODO: Review)
|
||||||
|
case 3: break; // TEXT: No parameters
|
||||||
|
case 4: break; // RAW: No parameters
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Jump DATA to read next infoHeader
|
||||||
|
fseek(rresFile, infoHeader.size, SEEK_CUR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(rresFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(rresFile);
|
if (!found) TraceLog(WARNING, "[%s] Required resource id [%i] could not be found in the raylib resource file", rresName, resId);
|
||||||
|
|
||||||
if (!found) printf("Required resource id could not be found in the raylib Resource file!\n");
|
|
||||||
|
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
@ -218,11 +246,33 @@ Image LoadImageFromRES(const char *rresName, int resId)
|
||||||
Texture2D LoadTexture(const char *fileName)
|
Texture2D LoadTexture(const char *fileName)
|
||||||
{
|
{
|
||||||
Texture2D texture;
|
Texture2D texture;
|
||||||
Image image;
|
|
||||||
|
if (strcmp(GetExtension(fileName),"dds") == 0)
|
||||||
image = LoadImage(fileName);
|
{
|
||||||
texture = CreateTexture(image);
|
#ifdef USE_OPENGL_11
|
||||||
UnloadImage(image);
|
TraceLog(WARNING, "[%s] DDS file loading requires OpenGL 3.2+ or ES 2.0", fileName);
|
||||||
|
#else
|
||||||
|
ImageDDS image = LoadDDS(fileName);
|
||||||
|
|
||||||
|
texture.glId = rlglLoadCompressedTexture(image.data, image.width, image.height, image.mipmaps, image.format);
|
||||||
|
|
||||||
|
texture.width = image.width;
|
||||||
|
texture.height = image.height;
|
||||||
|
|
||||||
|
if (texture.glId == 0) TraceLog(WARNING, "Compressed texture could not be loaded");
|
||||||
|
else TraceLog(INFO, "Compressed texture loaded succesfully");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Image image = LoadImage(fileName);
|
||||||
|
|
||||||
|
if (image.pixels != NULL)
|
||||||
|
{
|
||||||
|
texture = CreateTexture(image);
|
||||||
|
UnloadImage(image);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
@ -238,43 +288,6 @@ Texture2D LoadTextureFromRES(const char *rresName, int resId)
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a Texture2D from Image data
|
|
||||||
// NOTE: Image is not unloaded, it should be done manually...
|
|
||||||
Texture2D CreateTexture(Image image)
|
|
||||||
{
|
|
||||||
Texture2D texture;
|
|
||||||
|
|
||||||
// Convert image data to OpenGL texture
|
|
||||||
//----------------------------------------
|
|
||||||
GLuint id;
|
|
||||||
glGenTextures(1, &id); // Generate Pointer to the Texture
|
|
||||||
|
|
||||||
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
|
|
||||||
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
|
|
||||||
|
|
||||||
// Trilinear filtering
|
|
||||||
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
||||||
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); // Activate use of mipmaps (must be available)
|
|
||||||
//glGenerateMipmap(GL_TEXTURE_2D); // OpenGL 3.3!
|
|
||||||
|
|
||||||
// Upload texture to GPU
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, image.width, image.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image.pixels);
|
|
||||||
|
|
||||||
// NOTE: Not using mipmappings (texture for 2D drawing)
|
|
||||||
// At this point we have the image converted to texture and uploaded to GPU
|
|
||||||
|
|
||||||
texture.glId = id;
|
|
||||||
texture.width = image.width;
|
|
||||||
texture.height = image.height;
|
|
||||||
|
|
||||||
return texture;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unload image from CPU memory (RAM)
|
// Unload image from CPU memory (RAM)
|
||||||
void UnloadImage(Image image)
|
void UnloadImage(Image image)
|
||||||
{
|
{
|
||||||
|
@ -284,13 +297,13 @@ void UnloadImage(Image image)
|
||||||
// Unload texture from GPU memory
|
// Unload texture from GPU memory
|
||||||
void UnloadTexture(Texture2D texture)
|
void UnloadTexture(Texture2D texture)
|
||||||
{
|
{
|
||||||
glDeleteTextures(1, &texture.glId);
|
rlDeleteTextures(texture.glId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw a Texture2D
|
// Draw a Texture2D
|
||||||
void DrawTexture(Texture2D texture, int posX, int posY, Color tint)
|
void DrawTexture(Texture2D texture, int posX, int posY, Color tint)
|
||||||
{
|
{
|
||||||
DrawTextureEx(texture, (Vector2){ (float)posX, (float)posY}, 0, 1.0f, tint);
|
DrawTextureEx(texture, (Vector2){ (float)posX, (float)posY }, 0, 1.0f, tint);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw a Texture2D with position defined as Vector2
|
// Draw a Texture2D with position defined as Vector2
|
||||||
|
@ -302,101 +315,233 @@ void DrawTextureV(Texture2D texture, Vector2 position, Color tint)
|
||||||
// Draw a Texture2D with extended parameters
|
// Draw a Texture2D with extended parameters
|
||||||
void DrawTextureEx(Texture2D texture, Vector2 position, float rotation, float scale, Color tint)
|
void DrawTextureEx(Texture2D texture, Vector2 position, float rotation, float scale, Color tint)
|
||||||
{
|
{
|
||||||
glEnable(GL_TEXTURE_2D); // Enable textures usage
|
rlEnableTexture(texture.glId);
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, texture.glId);
|
// NOTE: Rotation is applied before translation and scaling, even being called in inverse order...
|
||||||
|
// NOTE: Rotation point is upper-left corner
|
||||||
|
rlPushMatrix();
|
||||||
|
//rlTranslatef(position.x, position.y, 0.0);
|
||||||
|
rlRotatef(rotation, 0, 0, 1);
|
||||||
|
rlScalef(scale, scale, 1.0f);
|
||||||
|
|
||||||
glPushMatrix();
|
rlBegin(RL_QUADS);
|
||||||
// NOTE: Rotation is applied before translation and scaling, even being called in inverse order...
|
rlColor4ub(tint.r, tint.g, tint.b, tint.a);
|
||||||
// NOTE: Rotation point is upper-left corner
|
rlNormal3f(0.0f, 0.0f, 1.0f); // Normal vector pointing towards viewer
|
||||||
glTranslatef(position.x, position.y, 0);
|
|
||||||
glScalef(scale, scale, 1.0f);
|
rlTexCoord2f(0.0f, 0.0f);
|
||||||
glRotatef(rotation, 0, 0, 1);
|
rlVertex2f(position.x, position.y); // Bottom-left corner for texture and quad
|
||||||
|
|
||||||
glBegin(GL_QUADS);
|
rlTexCoord2f(0.0f, 1.0f);
|
||||||
glColor4ub(tint.r, tint.g, tint.b, tint.a);
|
rlVertex2f(position.x, position.y + texture.height); // Bottom-right corner for texture and quad
|
||||||
glNormal3f(0.0f, 0.0f, 1.0f); // Normal vector pointing towards viewer
|
|
||||||
glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f, 0.0f); // Bottom-left corner for texture and quad
|
rlTexCoord2f(1.0f, 1.0f);
|
||||||
glTexCoord2f(1.0f, 0.0f); glVertex2f(texture.width, 0.0f); // Bottom-right corner for texture and quad
|
rlVertex2f(position.x + texture.width, position.y + texture.height); // Top-right corner for texture and quad
|
||||||
glTexCoord2f(1.0f, 1.0f); glVertex2f(texture.width, texture.height); // Top-right corner for texture and quad
|
|
||||||
glTexCoord2f(0.0f, 1.0f); glVertex2f(0.0f, texture.height); // Top-left corner for texture and quad
|
rlTexCoord2f(1.0f, 0.0f);
|
||||||
glEnd();
|
rlVertex2f(position.x + texture.width, position.y); // Top-left corner for texture and quad
|
||||||
glPopMatrix();
|
rlEnd();
|
||||||
|
rlPopMatrix();
|
||||||
|
|
||||||
glDisable(GL_TEXTURE_2D); // Disable textures usage
|
rlDisableTexture();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw a part of a texture (defined by a rectangle)
|
// Draw a part of a texture (defined by a rectangle)
|
||||||
void DrawTextureRec(Texture2D texture, Rectangle sourceRec, Vector2 position, Color tint)
|
void DrawTextureRec(Texture2D texture, Rectangle sourceRec, Vector2 position, Color tint)
|
||||||
{
|
{
|
||||||
glEnable(GL_TEXTURE_2D); // Enable textures usage
|
rlEnableTexture(texture.glId);
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, texture.glId);
|
rlBegin(RL_QUADS);
|
||||||
|
rlColor4ub(tint.r, tint.g, tint.b, tint.a);
|
||||||
glPushMatrix();
|
rlNormal3f(0.0f, 0.0f, 1.0f); // Normal vector pointing towards viewer
|
||||||
glTranslatef(position.x, position.y, 0);
|
|
||||||
//glScalef(1.0f, 1.0f, 1.0f);
|
|
||||||
//glRotatef(rotation, 0, 0, 1);
|
|
||||||
|
|
||||||
glBegin(GL_QUADS);
|
// Bottom-left corner for texture and quad
|
||||||
glColor4ub(tint.r, tint.g, tint.b, tint.a);
|
rlTexCoord2f((float)sourceRec.x / texture.width, (float)sourceRec.y / texture.height);
|
||||||
glNormal3f(0.0f, 0.0f, 1.0f); // Normal vector pointing towards viewer
|
rlVertex2f(position.x, position.y);
|
||||||
|
|
||||||
// Bottom-left corner for texture and quad
|
// Bottom-right corner for texture and quad
|
||||||
glTexCoord2f((float)sourceRec.x / texture.width, (float)sourceRec.y / texture.height);
|
rlTexCoord2f((float)sourceRec.x / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height);
|
||||||
glVertex2f(0.0f, 0.0f);
|
rlVertex2f(position.x, position.y + sourceRec.height);
|
||||||
|
|
||||||
// Bottom-right corner for texture and quad
|
// Top-right corner for texture and quad
|
||||||
glTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)sourceRec.y / texture.height);
|
rlTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height);
|
||||||
glVertex2f(sourceRec.width, 0.0f);
|
rlVertex2f(position.x + sourceRec.width, position.y + sourceRec.height);
|
||||||
|
|
||||||
// Top-right corner for texture and quad
|
// Top-left corner for texture and quad
|
||||||
glTexCoord2f((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 / texture.height);
|
||||||
glVertex2f(sourceRec.width, sourceRec.height);
|
rlVertex2f(position.x + sourceRec.width, position.y);
|
||||||
|
rlEnd();
|
||||||
// Top-left corner for texture and quad
|
|
||||||
glTexCoord2f((float)sourceRec.x / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height);
|
|
||||||
glVertex2f(0.0f, sourceRec.height);
|
|
||||||
glEnd();
|
|
||||||
glPopMatrix();
|
|
||||||
|
|
||||||
glDisable(GL_TEXTURE_2D); // Disable textures usage
|
rlDisableTexture();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw a part of a texture (defined by a rectangle) with 'pro' parameters
|
// Draw a part of a texture (defined by a rectangle) with 'pro' parameters
|
||||||
// TODO: Test this function...
|
// TODO: Test this function...
|
||||||
void DrawTexturePro(Texture2D texture, Rectangle sourceRec, Rectangle destRec, Vector2 origin, float rotation, Color tint)
|
void DrawTexturePro(Texture2D texture, Rectangle sourceRec, Rectangle destRec, Vector2 origin, float rotation, Color tint)
|
||||||
{
|
{
|
||||||
glEnable(GL_TEXTURE_2D); // Enable textures usage
|
rlEnableTexture(texture.glId);
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, texture.glId);
|
// NOTE: First we translate texture to origin to apply rotation and translation from there
|
||||||
|
rlPushMatrix();
|
||||||
glPushMatrix();
|
rlTranslatef(-origin.x, -origin.y, 0);
|
||||||
glTranslatef(-origin.x, -origin.y, 0);
|
rlRotatef(rotation, 0, 0, 1);
|
||||||
glRotatef(rotation, 0, 0, 1);
|
rlTranslatef(destRec.x + origin.x, destRec.y + origin.y, 0);
|
||||||
glTranslatef(destRec.x + origin.x, destRec.y + origin.y, 0);
|
|
||||||
|
rlBegin(RL_QUADS);
|
||||||
glBegin(GL_QUADS);
|
rlColor4ub(tint.r, tint.g, tint.b, tint.a);
|
||||||
glColor4ub(tint.r, tint.g, tint.b, tint.a);
|
rlNormal3f(0.0f, 0.0f, 1.0f); // Normal vector pointing towards viewer
|
||||||
glNormal3f(0.0f, 0.0f, 1.0f); // Normal vector pointing towards viewer
|
|
||||||
|
|
||||||
// Bottom-left corner for texture and quad
|
// Bottom-left corner for texture and quad
|
||||||
glTexCoord2f((float)sourceRec.x / texture.width, (float)sourceRec.y / texture.height);
|
rlTexCoord2f((float)sourceRec.x / texture.width, (float)sourceRec.y / texture.height);
|
||||||
glVertex2f(0.0f, 0.0f);
|
rlVertex2f(0.0f, 0.0f);
|
||||||
|
|
||||||
// Bottom-right corner for texture and quad
|
// Bottom-right corner for texture and quad
|
||||||
glTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)sourceRec.y / texture.height);
|
rlTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)sourceRec.y / texture.height);
|
||||||
glVertex2f(destRec.width, 0.0f);
|
rlVertex2f(destRec.width, 0.0f);
|
||||||
|
|
||||||
// Top-right corner for texture and quad
|
// Top-right corner for texture and quad
|
||||||
glTexCoord2f((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);
|
||||||
glVertex2f(destRec.width, destRec.height);
|
rlVertex2f(destRec.width, destRec.height);
|
||||||
|
|
||||||
// Top-left corner for texture and quad
|
// Top-left corner for texture and quad
|
||||||
glTexCoord2f((float)sourceRec.x / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height);
|
rlTexCoord2f((float)sourceRec.x / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height);
|
||||||
glVertex2f(0.0f, destRec.height);
|
rlVertex2f(0.0f, destRec.height);
|
||||||
glEnd();
|
rlEnd();
|
||||||
glPopMatrix();
|
rlPopMatrix();
|
||||||
|
|
||||||
glDisable(GL_TEXTURE_2D); // Disable textures usage
|
rlDisableTexture();
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture2D CreateTexture(Image image)
|
||||||
|
{
|
||||||
|
Texture2D texture;
|
||||||
|
|
||||||
|
unsigned char *img = malloc(image.width * image.height * 4);
|
||||||
|
|
||||||
|
int j = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < image.width * image.height * 4; i += 4)
|
||||||
|
{
|
||||||
|
img[i] = image.pixels[j].r;
|
||||||
|
img[i+1] = image.pixels[j].g;
|
||||||
|
img[i+2] = image.pixels[j].b;
|
||||||
|
img[i+3] = image.pixels[j].a;
|
||||||
|
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
|
||||||
|
texture.glId = rlglLoadTexture(image.width, image.height, img);
|
||||||
|
|
||||||
|
texture.width = image.width;
|
||||||
|
texture.height = image.height;
|
||||||
|
|
||||||
|
TraceLog(INFO, "Texture created succesfully");
|
||||||
|
|
||||||
|
free(img);
|
||||||
|
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the extension for a filename
|
||||||
|
static const char *GetExtension(const char *fileName)
|
||||||
|
{
|
||||||
|
const char *dot = strrchr(fileName, '.');
|
||||||
|
if(!dot || dot == fileName) return "";
|
||||||
|
return (dot + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loading DDS image compressed data
|
||||||
|
ImageDDS LoadDDS(const char *fileName)
|
||||||
|
{
|
||||||
|
// TODO: Review and expand DDS file loading to support uncompressed formats and new formats
|
||||||
|
|
||||||
|
// DDS Pixel Format
|
||||||
|
typedef struct {
|
||||||
|
unsigned int size;
|
||||||
|
unsigned int flags;
|
||||||
|
unsigned int fourCC;
|
||||||
|
unsigned int rgbBitCount;
|
||||||
|
unsigned int rBitMask;
|
||||||
|
unsigned int gBitMask;
|
||||||
|
unsigned int bitMask;
|
||||||
|
unsigned int aBitMask;
|
||||||
|
} ddsPixelFormat;
|
||||||
|
|
||||||
|
// DDS Header (124 bytes)
|
||||||
|
typedef struct {
|
||||||
|
unsigned int size;
|
||||||
|
unsigned int flags;
|
||||||
|
unsigned int height;
|
||||||
|
unsigned int width;
|
||||||
|
unsigned int pitchOrLinearSize;
|
||||||
|
unsigned int depth;
|
||||||
|
unsigned int mipMapCount;
|
||||||
|
unsigned int reserved1[11];
|
||||||
|
ddsPixelFormat ddspf;
|
||||||
|
unsigned int caps;
|
||||||
|
unsigned int caps2;
|
||||||
|
unsigned int caps3;
|
||||||
|
unsigned int caps4;
|
||||||
|
unsigned int reserved2;
|
||||||
|
} ddsHeader;
|
||||||
|
|
||||||
|
ImageDDS image;
|
||||||
|
ddsHeader header;
|
||||||
|
|
||||||
|
FILE *ddsFile = fopen(fileName, "rb");
|
||||||
|
|
||||||
|
if (ddsFile == NULL)
|
||||||
|
{
|
||||||
|
TraceLog(WARNING, "DDS File could not be opened");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Verify the type of file
|
||||||
|
char filecode[4];
|
||||||
|
|
||||||
|
fread(filecode, 1, 4, ddsFile);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
int height = header.height;
|
||||||
|
int width = header.width;
|
||||||
|
int linearSize = header.pitchOrLinearSize;
|
||||||
|
int mipMapCount = header.mipMapCount;
|
||||||
|
int fourCC = header.ddspf.fourCC;
|
||||||
|
|
||||||
|
TraceLog(DEBUG, "[%s] DDS file header size: %i", fileName, sizeof(ddsHeader));
|
||||||
|
|
||||||
|
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, fourCC);
|
||||||
|
|
||||||
|
int bufsize;
|
||||||
|
|
||||||
|
// Calculate data size, including all mipmaps
|
||||||
|
bufsize = mipMapCount > 1 ? linearSize * 2 : linearSize;
|
||||||
|
|
||||||
|
image.data = (unsigned char*)malloc(bufsize * sizeof(unsigned char));
|
||||||
|
|
||||||
|
fread(image.data, 1, bufsize, ddsFile);
|
||||||
|
|
||||||
|
// Close file pointer
|
||||||
|
fclose(ddsFile);
|
||||||
|
|
||||||
|
//int components = (fourCC == FOURCC_DXT1) ? 3 : 4; // Not required
|
||||||
|
|
||||||
|
image.width = width;
|
||||||
|
image.height = height;
|
||||||
|
image.mipmaps = mipMapCount;
|
||||||
|
image.format = fourCC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return image;
|
||||||
}
|
}
|
148
src/utils.c
148
src/utils.c
|
@ -29,7 +29,8 @@
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
#include <stdlib.h> // malloc(), free()
|
#include <stdlib.h> // malloc(), free()
|
||||||
#include <stdio.h> // printf()
|
#include <stdio.h> // printf(), fprintf()
|
||||||
|
#include <stdarg.h> // Used for functions with variable number of parameters (TraceLog())
|
||||||
//#include <string.h> // String management functions: strlen(), strrchr(), strcmp()
|
//#include <string.h> // String management functions: strlen(), strrchr(), strcmp()
|
||||||
|
|
||||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||||
|
@ -37,6 +38,15 @@
|
||||||
#include "stb_image_write.h" // Create PNG file
|
#include "stb_image_write.h" // Create PNG file
|
||||||
#include "tinfl.c"
|
#include "tinfl.c"
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Global Variables Definition
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
static FILE *logstream = NULL;
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Module Functions Definition - Utilities
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Data decompression function
|
// Data decompression function
|
||||||
// NOTE: Allocated data MUST be freed!
|
// NOTE: Allocated data MUST be freed!
|
||||||
unsigned char *DecompressData(const unsigned char *data, unsigned long compSize, int uncompSize)
|
unsigned char *DecompressData(const unsigned char *data, unsigned long compSize, int uncompSize)
|
||||||
|
@ -50,28 +60,28 @@ unsigned char *DecompressData(const unsigned char *data, unsigned long compSize,
|
||||||
// Check correct memory allocation
|
// Check correct memory allocation
|
||||||
if (!pUncomp)
|
if (!pUncomp)
|
||||||
{
|
{
|
||||||
printf("Out of memory!\n");
|
TraceLog(WARNING, "Out of memory while decompressing data");
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
// Decompress data
|
|
||||||
tempUncompSize = tinfl_decompress_mem_to_mem(pUncomp, (size_t)uncompSize, data, compSize, 1);
|
|
||||||
|
|
||||||
if (tempUncompSize == -1)
|
|
||||||
{
|
{
|
||||||
printf("Decompression failed!\n");
|
// Decompress data
|
||||||
free(pUncomp);
|
tempUncompSize = tinfl_decompress_mem_to_mem(pUncomp, (size_t)uncompSize, data, compSize, 1);
|
||||||
return NULL;
|
|
||||||
}
|
if (tempUncompSize == -1)
|
||||||
|
{
|
||||||
if (uncompSize != (int)tempUncompSize)
|
TraceLog(WARNING, "Data decompression failed");
|
||||||
{
|
free(pUncomp);
|
||||||
printf("WARNING! Expected uncompressed size do not match! Data may be corrupted!\n");
|
}
|
||||||
printf(" -- Expected uncompressed size: %i\n", uncompSize);
|
|
||||||
printf(" -- Returned uncompressed size: %i\n", tempUncompSize);
|
if (uncompSize != (int)tempUncompSize)
|
||||||
}
|
{
|
||||||
|
TraceLog(WARNING, "Expected uncompressed size do not match, data may be corrupted");
|
||||||
|
TraceLog(WARNING, " -- Expected uncompressed size: %i", uncompSize);
|
||||||
|
TraceLog(WARNING, " -- Returned uncompressed size: %i", tempUncompSize);
|
||||||
|
}
|
||||||
|
|
||||||
printf("Decompressed from %u bytes to %u bytes\n", (mz_uint32)compSize, (mz_uint32)tempUncompSize);
|
TraceLog(INFO, "Data decompressed successfully from %u bytes to %u bytes", (mz_uint32)compSize, (mz_uint32)tempUncompSize);
|
||||||
|
}
|
||||||
|
|
||||||
return pUncomp;
|
return pUncomp;
|
||||||
}
|
}
|
||||||
|
@ -124,4 +134,100 @@ void WriteBitmap(const char *fileName, unsigned char *imgData, int width, int he
|
||||||
void WritePNG(const char *fileName, unsigned char *imgData, int width, int height)
|
void WritePNG(const char *fileName, unsigned char *imgData, int width, int height)
|
||||||
{
|
{
|
||||||
stbi_write_png(fileName, width, height, 4, imgData, width*4); // It WORKS!!!
|
stbi_write_png(fileName, width, height, 4, imgData, width*4); // It WORKS!!!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Outputs a trace log message (INFO, ERROR, WARNING)
|
||||||
|
// NOTE: If a file has been init, output log is written there
|
||||||
|
void TraceLog(int msgType, const char *text, ...)
|
||||||
|
{
|
||||||
|
// TODO: This function requires some refactoring...
|
||||||
|
|
||||||
|
// NOTE: If trace log file has been set, stdout is being redirected to a file
|
||||||
|
va_list args;
|
||||||
|
int traceDebugMsgs = 1;
|
||||||
|
|
||||||
|
#ifdef DO_NOT_TRACE_DEBUG_MSGS
|
||||||
|
traceDebugMsgs = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (logstream != NULL)
|
||||||
|
{
|
||||||
|
switch(msgType)
|
||||||
|
{
|
||||||
|
case 0: fprintf(logstream, "INFO: "); break;
|
||||||
|
case 1: fprintf(logstream, "ERROR: "); break;
|
||||||
|
case 2: fprintf(logstream, "WARNING: "); break;
|
||||||
|
case 3: if (traceDebugMsgs) fprintf(logstream, "DEBUG: "); break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msgType == 3)
|
||||||
|
{
|
||||||
|
if (traceDebugMsgs)
|
||||||
|
{
|
||||||
|
va_start(args, text);
|
||||||
|
vfprintf(logstream, text, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
fprintf(logstream, "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
va_start(args, text);
|
||||||
|
vfprintf(logstream, text, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
fprintf(logstream, "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch(msgType)
|
||||||
|
{
|
||||||
|
case 0: fprintf(stdout, "INFO: "); break;
|
||||||
|
case 1: fprintf(stdout, "ERROR: "); break;
|
||||||
|
case 2: fprintf(stdout, "WARNING: "); break;
|
||||||
|
case 3: if (traceDebugMsgs) fprintf(stdout, "DEBUG: "); break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msgType == 3)
|
||||||
|
{
|
||||||
|
if (traceDebugMsgs)
|
||||||
|
{
|
||||||
|
va_start(args, text);
|
||||||
|
vfprintf(stdout, text, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
fprintf(stdout, "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
va_start(args, text);
|
||||||
|
vfprintf(stdout, text, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
fprintf(stdout, "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msgType == 1) exit(1); // If ERROR message, exit program
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inits a trace log file
|
||||||
|
void InitTraceLogFile(const char *logFileName)
|
||||||
|
{
|
||||||
|
// stdout redirected to stream file
|
||||||
|
FILE *logstream = fopen(logFileName, "w");
|
||||||
|
|
||||||
|
if (logstream == NULL) TraceLog(WARNING, "Unable to open log file");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Closes the trace log file
|
||||||
|
void CloseTraceLogFile()
|
||||||
|
{
|
||||||
|
if (logstream != NULL) fclose(logstream);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,13 +32,15 @@
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Some basic Defines
|
// Some basic Defines
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
//...
|
//#define DO_NOT_TRACE_DEBUG_MSGS // Use this define to avoid DEBUG tracing
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Types and Structures Definition
|
// Types and Structures Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
typedef enum { IMAGE, SOUND, MODEL, TEXT, RAW } DataType;
|
typedef enum { IMAGE, SOUND, MODEL, TEXT, RAW } DataType;
|
||||||
|
|
||||||
|
typedef enum { INFO = 0, ERROR, WARNING, DEBUG, OTHER } TraceLogType;
|
||||||
|
|
||||||
// One resource info header, every resource includes this header (8 byte)
|
// One resource info header, every resource includes this header (8 byte)
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned short id; // Resource unique identifier (2 byte)
|
unsigned short id; // Resource unique identifier (2 byte)
|
||||||
|
@ -61,9 +63,14 @@ extern "C" { // Prevents name mangling of functions
|
||||||
// Module Functions Declaration
|
// Module Functions Declaration
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
unsigned char *DecompressData(const unsigned char *data, unsigned long compSize, int uncompSize);
|
unsigned char *DecompressData(const unsigned char *data, unsigned long compSize, int uncompSize);
|
||||||
|
|
||||||
void WriteBitmap(const char *fileName, unsigned char *imgData, int width, int height);
|
void WriteBitmap(const char *fileName, unsigned char *imgData, int width, int height);
|
||||||
void WritePNG(const char *fileName, unsigned char *imgData, int width, int height);
|
void WritePNG(const char *fileName, unsigned char *imgData, int width, int height);
|
||||||
|
|
||||||
|
void TraceLog(int msgType, const char *text, ...); // Outputs a trace log message
|
||||||
|
void InitTraceLogFile(const char *logFileName); // Inits a trace log file
|
||||||
|
void CloseTraceLogFile(); // Closes the trace log file
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
140
src/vector3.c
140
src/vector3.c
|
@ -1,140 +0,0 @@
|
||||||
/*********************************************************************************************
|
|
||||||
*
|
|
||||||
* raylib.vector3
|
|
||||||
*
|
|
||||||
* Vector3 Functions Definition
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
* 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
|
|
||||||
* 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
|
|
||||||
* 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
|
|
||||||
* as being the original software.
|
|
||||||
*
|
|
||||||
* 3. This notice may not be removed or altered from any source distribution.
|
|
||||||
*
|
|
||||||
**********************************************************************************************/
|
|
||||||
|
|
||||||
#include "vector3.h"
|
|
||||||
|
|
||||||
#include <math.h> // Used for fabs(), sqrt()
|
|
||||||
|
|
||||||
// Add two vectors
|
|
||||||
Vector3 VectorAdd(Vector3 v1, Vector3 v2)
|
|
||||||
{
|
|
||||||
Vector3 out;
|
|
||||||
|
|
||||||
out.x = v1.x + v2.x;
|
|
||||||
out.y = v1.y + v2.y;
|
|
||||||
out.z = v1.z + v2.z;
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Substract two vectors
|
|
||||||
Vector3 VectorSubtract(Vector3 v1, Vector3 v2)
|
|
||||||
{
|
|
||||||
Vector3 out;
|
|
||||||
|
|
||||||
out.x = v1.x - v2.x;
|
|
||||||
out.y = v1.y - v2.y;
|
|
||||||
out.z = v1.z - v2.z;
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate two vectors cross product
|
|
||||||
Vector3 VectorCrossProduct(Vector3 v1, Vector3 v2)
|
|
||||||
{
|
|
||||||
Vector3 cross;
|
|
||||||
|
|
||||||
cross.x = v1.y*v2.z - v1.z*v2.y;
|
|
||||||
cross.y = v1.z*v2.x - v1.x*v2.z;
|
|
||||||
cross.z = v1.x*v2.y - v1.y*v2.x;
|
|
||||||
|
|
||||||
return cross;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate one vector perpendicular vector
|
|
||||||
Vector3 VectorPerpendicular(Vector3 v)
|
|
||||||
{
|
|
||||||
Vector3 out;
|
|
||||||
|
|
||||||
float min = fabs(v.x);
|
|
||||||
Vector3 cardinalAxis = {1.0, 0.0, 0.0};
|
|
||||||
|
|
||||||
if (fabs(v.y) < min)
|
|
||||||
{
|
|
||||||
min = fabs(v.y);
|
|
||||||
cardinalAxis = (Vector3){0.0, 1.0, 0.0};
|
|
||||||
}
|
|
||||||
|
|
||||||
if(fabs(v.z) < min)
|
|
||||||
{
|
|
||||||
cardinalAxis = (Vector3){0.0, 0.0, 1.0};
|
|
||||||
}
|
|
||||||
|
|
||||||
out = VectorCrossProduct(v, cardinalAxis);
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate two vectors dot product
|
|
||||||
float VectorDotProduct(Vector3 v1, Vector3 v2)
|
|
||||||
{
|
|
||||||
float dot;
|
|
||||||
|
|
||||||
dot = v1.x*v2.x + v1.y*v2.y + v1.z*v2.z;
|
|
||||||
|
|
||||||
return dot;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate vector lenght
|
|
||||||
float VectorLength(const Vector3 v)
|
|
||||||
{
|
|
||||||
float length;
|
|
||||||
|
|
||||||
length = sqrt(v.x*v.x + v.y*v.y + v.z*v.z);
|
|
||||||
|
|
||||||
return length;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scale provided vector
|
|
||||||
void VectorScale(Vector3 *v, float scale)
|
|
||||||
{
|
|
||||||
v->x *= scale;
|
|
||||||
v->y *= scale;
|
|
||||||
v->z *= scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Invert provided vector (direction)
|
|
||||||
void VectorInverse(Vector3 *v)
|
|
||||||
{
|
|
||||||
v->x = -v->x;
|
|
||||||
v->y = -v->y;
|
|
||||||
v->z = -v->z;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Normalize provided vector
|
|
||||||
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;
|
|
||||||
}
|
|
|
@ -1,57 +0,0 @@
|
||||||
/*********************************************************************************************
|
|
||||||
*
|
|
||||||
* raylib.vector3
|
|
||||||
*
|
|
||||||
* Some useful functions to work with Vector3
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
* 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
|
|
||||||
* 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
|
|
||||||
* 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
|
|
||||||
* as being the original software.
|
|
||||||
*
|
|
||||||
* 3. This notice may not be removed or altered from any source distribution.
|
|
||||||
*
|
|
||||||
**********************************************************************************************/
|
|
||||||
|
|
||||||
#ifndef VECTOR3_H
|
|
||||||
#define VECTOR3_H
|
|
||||||
|
|
||||||
#include "raylib.h" // Defines Vector3 structure
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" { // Prevents name mangling of functions
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------
|
|
||||||
// Global Variables Definition
|
|
||||||
//------------------------------------------------------------------------------------
|
|
||||||
// It's lonely here...
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------
|
|
||||||
// Functions Declaration to work with Vector3
|
|
||||||
//------------------------------------------------------------------------------------
|
|
||||||
Vector3 VectorAdd(Vector3 v1, Vector3 v2); // Add two vectors
|
|
||||||
Vector3 VectorSubtract(Vector3 v1, Vector3 v2); // Substract two vectors
|
|
||||||
Vector3 VectorCrossProduct(Vector3 v1, Vector3 v2); // Calculate two vectors cross product
|
|
||||||
Vector3 VectorPerpendicular(Vector3 v); // Calculate one vector perpendicular vector
|
|
||||||
float VectorDotProduct(Vector3 v1, Vector3 v2); // Calculate two vectors dot product
|
|
||||||
float VectorLength(const Vector3 v); // Calculate vector lenght
|
|
||||||
void VectorScale(Vector3 *v, float scale); // Scale provided vector
|
|
||||||
void VectorInverse(Vector3 *v); // Invert provided vector (direction)
|
|
||||||
void VectorNormalize(Vector3 *v); // Normalize provided vector
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // VECTOR3_H
|
|
Loading…
Add table
Add a link
Reference in a new issue