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 "stb_vorbis.h" // TODO: OGG loading functions
|
||||
//#include "stb_vorbis.h" // OGG loading functions
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Defines and Macros
|
||||
|
@ -47,6 +47,29 @@
|
|||
//----------------------------------------------------------------------------------
|
||||
// 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
|
||||
typedef struct Wave {
|
||||
|
@ -60,7 +83,8 @@ typedef struct Wave {
|
|||
//----------------------------------------------------------------------------------
|
||||
// Global Variables Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
// Nop...
|
||||
static bool musicIsPlaying;
|
||||
static Music *currentMusic;
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module specific Functions Declaration
|
||||
|
@ -68,6 +92,10 @@ typedef struct Wave {
|
|||
static Wave LoadWAV(char *fileName);
|
||||
static void UnloadWAV(Wave wave);
|
||||
//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
|
||||
|
@ -79,30 +107,27 @@ void InitAudioDevice()
|
|||
// Open and initialize a device with default settings
|
||||
ALCdevice *device = alcOpenDevice(NULL);
|
||||
|
||||
if(!device)
|
||||
{
|
||||
fprintf(stderr, "Could not open a device!\n");
|
||||
exit(1);
|
||||
}
|
||||
if(!device) TraceLog(ERROR, "Could not open audio device");
|
||||
|
||||
ALCcontext *context = alcCreateContext(device, NULL);
|
||||
|
||||
if(context == NULL || alcMakeContextCurrent(context) == ALC_FALSE)
|
||||
{
|
||||
if(context != NULL) alcDestroyContext(context);
|
||||
if(context != NULL) alcDestroyContext(context);
|
||||
|
||||
alcCloseDevice(device);
|
||||
|
||||
fprintf(stderr, "Could not set a context!\n");
|
||||
exit(1);
|
||||
TraceLog(ERROR, "Could not setup audio context");
|
||||
}
|
||||
|
||||
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)
|
||||
alListener3f(AL_POSITION, 0, 0, 0);
|
||||
alListener3f(AL_VELOCITY, 0, 0, 0);
|
||||
alListener3f(AL_ORIENTATION, 0, 0, -1);
|
||||
|
||||
musicIsPlaying = false;
|
||||
}
|
||||
|
||||
// Close the audio device for the current context, and destroys the context
|
||||
|
@ -111,7 +136,7 @@ void CloseAudioDevice()
|
|||
ALCdevice *device;
|
||||
ALCcontext *context = alcGetCurrentContext();
|
||||
|
||||
if (context == NULL) return;
|
||||
if (context == NULL) TraceLog(WARNING, "Could not get current audio context for closing");
|
||||
|
||||
device = alcGetContextsDevice(context);
|
||||
|
||||
|
@ -131,7 +156,7 @@ Sound LoadSound(char *fileName)
|
|||
// NOTE: Buffer space is allocated inside LoadWAV, Wave must be freed
|
||||
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
|
||||
if (wave.channels == 1)
|
||||
{
|
||||
|
@ -169,10 +194,8 @@ Sound LoadSound(char *fileName)
|
|||
// Unallocate WAV data
|
||||
UnloadWAV(wave);
|
||||
|
||||
printf("Sample rate: %i\n", wave.sampleRate);
|
||||
printf("Channels: %i\n", wave.channels);
|
||||
|
||||
printf("Audio file loaded...!\n");
|
||||
TraceLog(INFO, "[%s] Sound file loaded successfully", fileName);
|
||||
TraceLog(INFO, "[%s] Sample rate: %i - Channels: %i", fileName, wave.sampleRate, wave.channels);
|
||||
|
||||
sound.source = source;
|
||||
sound.buffer = buffer;
|
||||
|
@ -196,139 +219,136 @@ Sound LoadSoundFromRES(const char *rresName, int resId)
|
|||
|
||||
FILE *rresFile = fopen(rresName, "rb");
|
||||
|
||||
if (!rresFile) printf("Error opening raylib Resource file\n");
|
||||
|
||||
// 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'))
|
||||
if (!rresFile) TraceLog(WARNING, "[%s] Could not open raylib resource file", rresName);
|
||||
else
|
||||
{
|
||||
printf("This is not a valid raylib Resource file!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Read number of resources embedded
|
||||
fread(&numRes, sizeof(short), 1, rresFile);
|
||||
|
||||
for (int i = 0; i < numRes; i++)
|
||||
{
|
||||
fread(&infoHeader, sizeof(ResInfoHeader), 1, rresFile);
|
||||
// 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 (infoHeader.id == resId)
|
||||
if ((id[0] != 'r') && (id[1] != 'R') && (id[2] != 'E') &&(id[3] != 'S'))
|
||||
{
|
||||
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>
|
||||
|
||||
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);
|
||||
}
|
||||
TraceLog(WARNING, "[%s] This is not a valid raylib resource file", 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;
|
||||
}
|
||||
// Read number of resources embedded
|
||||
fread(&numRes, sizeof(short), 1, rresFile);
|
||||
|
||||
// Jump DATA to read next infoHeader
|
||||
fseek(rresFile, infoHeader.size, SEEK_CUR);
|
||||
}
|
||||
for (int i = 0; i < numRes; i++)
|
||||
{
|
||||
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) printf("Required resource id could not be found in the raylib Resource file!\n");
|
||||
if (!found) TraceLog(WARNING, "[%s] Required resource id [%i] could not be found in the raylib resource file", rresName, resId);
|
||||
|
||||
return sound;
|
||||
}
|
||||
|
@ -345,7 +365,7 @@ void PlaySound(Sound sound)
|
|||
{
|
||||
alSourcePlay(sound.source); // Play the sound
|
||||
|
||||
printf("Playing sound!\n");
|
||||
TraceLog(INFO, "Playing sound");
|
||||
|
||||
// Find the current position of the sound being played
|
||||
// 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
|
||||
bool IsPlaying(Sound sound)
|
||||
bool SoundIsPlaying(Sound sound)
|
||||
{
|
||||
bool playing = false;
|
||||
ALint state;
|
||||
|
@ -401,6 +421,16 @@ bool IsPlaying(Sound sound)
|
|||
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
|
||||
void SetVolume(Sound sound, float volume)
|
||||
{
|
||||
|
@ -450,61 +480,65 @@ static Wave LoadWAV(char *fileName)
|
|||
|
||||
if (!wavFile)
|
||||
{
|
||||
printf("Could not open WAV file.\n");
|
||||
exit(1);
|
||||
TraceLog(WARNING, "[%s] Could not open WAV file", fileName);
|
||||
}
|
||||
|
||||
// Read in the first chunk into the struct
|
||||
fread(&riffHeader, sizeof(RiffHeader), 1, wavFile);
|
||||
|
||||
// Check for RIFF and WAVE tags
|
||||
if ((riffHeader.chunkID[0] != 'R' ||
|
||||
riffHeader.chunkID[1] != 'I' ||
|
||||
riffHeader.chunkID[2] != 'F' ||
|
||||
riffHeader.chunkID[3] != 'F') ||
|
||||
(riffHeader.format[0] != 'W' ||
|
||||
riffHeader.format[1] != 'A' ||
|
||||
riffHeader.format[2] != 'V' ||
|
||||
riffHeader.format[3] != 'E'))
|
||||
printf("Invalid RIFF or WAVE Header");
|
||||
|
||||
// Read in the 2nd chunk for the wave info
|
||||
fread(&waveFormat, sizeof(WaveFormat), 1, wavFile);
|
||||
|
||||
// Check for fmt tag
|
||||
if (waveFormat.subChunkID[0] != 'f' ||
|
||||
waveFormat.subChunkID[1] != 'm' ||
|
||||
waveFormat.subChunkID[2] != 't' ||
|
||||
waveFormat.subChunkID[3] != ' ')
|
||||
printf("Invalid Wave Format");
|
||||
|
||||
// Check for extra parameters;
|
||||
if (waveFormat.subChunkSize > 16)
|
||||
fseek(wavFile, sizeof(short), SEEK_CUR);
|
||||
|
||||
// Read in the the last byte of data before the sound file
|
||||
fread(&waveData, sizeof(WaveData), 1, wavFile);
|
||||
|
||||
// Check for data tag
|
||||
if (waveData.subChunkID[0] != 'd' ||
|
||||
waveData.subChunkID[1] != 'a' ||
|
||||
waveData.subChunkID[2] != 't' ||
|
||||
waveData.subChunkID[3] != 'a')
|
||||
printf("Invalid data header");
|
||||
|
||||
// Allocate memory for data
|
||||
wave.data = (unsigned char *)malloc(sizeof(unsigned char) * waveData.subChunkSize);
|
||||
|
||||
// Read in the sound data into the soundData variable
|
||||
fread(wave.data, waveData.subChunkSize, 1, wavFile);
|
||||
|
||||
// Now we set the variables that we need later
|
||||
wave.dataSize = waveData.subChunkSize;
|
||||
wave.sampleRate = waveFormat.sampleRate;
|
||||
wave.channels = waveFormat.numChannels;
|
||||
wave.bitsPerSample = waveFormat.bitsPerSample;
|
||||
else
|
||||
{
|
||||
// Read in the first chunk into the struct
|
||||
fread(&riffHeader, sizeof(RiffHeader), 1, wavFile);
|
||||
|
||||
// Check for RIFF and WAVE tags
|
||||
if (((riffHeader.chunkID[0] != 'R') || (riffHeader.chunkID[1] != 'I') || (riffHeader.chunkID[2] != 'F') || (riffHeader.chunkID[3] != 'F')) ||
|
||||
((riffHeader.format[0] != 'W') || (riffHeader.format[1] != 'A') || (riffHeader.format[2] != 'V') || (riffHeader.format[3] != 'E')))
|
||||
{
|
||||
TraceLog(WARNING, "[%s] Invalid RIFF or WAVE Header", fileName);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Read in the 2nd chunk for the wave info
|
||||
fread(&waveFormat, sizeof(WaveFormat), 1, wavFile);
|
||||
|
||||
// Check for fmt tag
|
||||
if ((waveFormat.subChunkID[0] != 'f') || (waveFormat.subChunkID[1] != 'm') ||
|
||||
(waveFormat.subChunkID[2] != 't') || (waveFormat.subChunkID[3] != ' '))
|
||||
{
|
||||
TraceLog(WARNING, "[%s] Invalid Wave format", fileName);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check for extra parameters;
|
||||
if (waveFormat.subChunkSize > 16) fseek(wavFile, sizeof(short), SEEK_CUR);
|
||||
|
||||
// Read in the the last byte of data before the sound file
|
||||
fread(&waveData, sizeof(WaveData), 1, wavFile);
|
||||
|
||||
// Check for data tag
|
||||
if ((waveData.subChunkID[0] != 'd') || (waveData.subChunkID[1] != 'a') ||
|
||||
(waveData.subChunkID[2] != 't') || (waveData.subChunkID[3] != 'a'))
|
||||
{
|
||||
TraceLog(WARNING, "[%s] Invalid data header", fileName);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Allocate memory for data
|
||||
wave.data = (unsigned char *)malloc(sizeof(unsigned char) * waveData.subChunkSize);
|
||||
|
||||
// Read in the sound data into the soundData variable
|
||||
fread(wave.data, waveData.subChunkSize, 1, wavFile);
|
||||
|
||||
// Now we set the variables that we need later
|
||||
wave.dataSize = waveData.subChunkSize;
|
||||
wave.sampleRate = waveFormat.sampleRate;
|
||||
wave.channels = waveFormat.numChannels;
|
||||
wave.bitsPerSample = waveFormat.bitsPerSample;
|
||||
|
||||
TraceLog(INFO, "[%s] Wave file loaded successfully", fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose(wavFile);
|
||||
fclose(wavFile);
|
||||
}
|
||||
|
||||
return wave;
|
||||
}
|
||||
|
@ -516,5 +550,192 @@ static void UnloadWAV(Wave wave)
|
|||
}
|
||||
|
||||
// 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 "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 <GL/gl.h> // OpenGL functions (GLFW3 already includes gl.h)
|
||||
#include <stdio.h> // Standard input / output lib
|
||||
#include <stdlib.h> // Declares malloc() and free() for memory management, rand()
|
||||
#include <time.h> // Useful to initialize random seed
|
||||
#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 "raymath.h" // Required for data type Matrix and Matrix functions
|
||||
|
||||
//#define GLFW_DLL // Using GLFW DLL on Windows -> No, we use static version!
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
|
@ -47,7 +51,7 @@
|
|||
//----------------------------------------------------------------------------------
|
||||
// Types and Structures Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
typedef Color pixel;
|
||||
// ...
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// 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 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 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 currentGamepadState[32] = {0}; // Required to check if gamepad btn pressed/released once
|
||||
|
||||
static int previousMouseWheelY = 0;
|
||||
static int currentMouseWheelY = 0;
|
||||
static int previousMouseWheelY = 0; // Required to track mouse wheel variation
|
||||
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)
|
||||
|
@ -86,16 +92,17 @@ static int currentMouseWheelY = 0;
|
|||
extern void LoadDefaultFont(); // [Module: text] Loads default font on InitWindow()
|
||||
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
|
||||
//----------------------------------------------------------------------------------
|
||||
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 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 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 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
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
|
@ -113,12 +120,20 @@ void InitWindowEx(int width, int height, const char* title, bool resizable, cons
|
|||
{
|
||||
glfwSetErrorCallback(ErrorCallback);
|
||||
|
||||
if (!glfwInit()) exit(1);
|
||||
if (!glfwInit()) TraceLog(ERROR, "Failed to initialize GLFW");
|
||||
|
||||
//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
|
||||
|
||||
|
||||
#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);
|
||||
|
||||
windowWidth = width;
|
||||
|
@ -128,7 +143,7 @@ void InitWindowEx(int width, int height, const char* title, bool resizable, cons
|
|||
if (!window)
|
||||
{
|
||||
glfwTerminate();
|
||||
exit(1);
|
||||
TraceLog(ERROR, "Failed to initialize Window");
|
||||
}
|
||||
|
||||
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)
|
||||
// If not set, swap interval uses GPU v-sync configuration
|
||||
// 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();
|
||||
|
||||
LoadDefaultFont();
|
||||
LoadDefaultFont(); // NOTE: External function (defined in module: text)
|
||||
|
||||
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
|
||||
void CloseWindow()
|
||||
{
|
||||
UnloadDefaultFont();
|
||||
|
||||
//------------------------------------------------------
|
||||
#if defined(USE_OPENGL_33) || defined(USE_OPENGL_ES2)
|
||||
rlglClose(); // De-init rlgl
|
||||
#endif
|
||||
//------------------------------------------------------
|
||||
|
||||
glfwDestroyWindow(window);
|
||||
glfwTerminate();
|
||||
|
@ -198,19 +233,30 @@ void ToggleFullscreen()
|
|||
// TODO: WARNING! All loaded resources are lost, we loose Context!
|
||||
|
||||
// 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);
|
||||
|
||||
|
||||
if (!window)
|
||||
{
|
||||
glfwTerminate();
|
||||
exit(1);
|
||||
TraceLog(ERROR, "Failed to initialize Window when switching fullscreen mode");
|
||||
}
|
||||
|
||||
glfwMakeContextCurrent(window);
|
||||
glfwSetKeyCallback(window, KeyCallback);
|
||||
|
||||
InitGraphicsDevice();
|
||||
int fbWidth, fbHeight;
|
||||
glfwGetFramebufferSize(window, &fbWidth, &fbHeight); // Get framebuffer size of current window
|
||||
|
||||
rlglInitGraphicsDevice(fbWidth, fbHeight);
|
||||
|
||||
LoadDefaultFont();
|
||||
}
|
||||
|
@ -219,13 +265,12 @@ void ToggleFullscreen()
|
|||
// Sets Background Color
|
||||
void ClearBackground(Color color)
|
||||
{
|
||||
// Color values clamp to 0.0f(0) and 1.0f(255)
|
||||
float r = (float)color.r / 255;
|
||||
float g = (float)color.g / 255;
|
||||
float b = (float)color.b / 255;
|
||||
float a = (float)color.a / 255;
|
||||
|
||||
glClearColor(r, g, b, a);
|
||||
if ((color.r != background.r) || (color.g != background.g) || (color.b != background.b) || (color.a != background.a))
|
||||
{
|
||||
rlClearColor(color.r, color.g, color.b, color.a);
|
||||
|
||||
background = color;
|
||||
}
|
||||
}
|
||||
|
||||
// Setup drawing canvas to start drawing
|
||||
|
@ -235,11 +280,14 @@ void BeginDrawing()
|
|||
updateTime = currentTime - previousTime;
|
||||
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)
|
||||
|
||||
glTranslatef(0.375, 0.375, 0); // HACK to have 2D pixel-perfect drawing on OpenGL
|
||||
rlLoadIdentity(); // Reset current matrix (MODELVIEW)
|
||||
|
||||
//#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)
|
||||
|
@ -247,9 +295,19 @@ void EndDrawing()
|
|||
{
|
||||
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
|
||||
glfwPollEvents(); // Register keyboard/mouse events
|
||||
|
||||
//MusicStreamUpdate();
|
||||
//if (!MusicIsPlaying())
|
||||
//PlayCurrentMusic();
|
||||
|
||||
currentTime = glfwGetTime();
|
||||
drawTime = currentTime - previousTime;
|
||||
previousTime = currentTime;
|
||||
|
@ -271,34 +329,48 @@ void EndDrawing()
|
|||
// Initializes 3D mode for drawing (Camera setup)
|
||||
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
|
||||
glLoadIdentity(); // Reset current matrix (PROJECTION)
|
||||
rlPushMatrix(); // Save previous matrix, which contains the settings for the 2d ortho projection
|
||||
rlLoadIdentity(); // Reset current matrix (PROJECTION)
|
||||
|
||||
// Setup perspective projection
|
||||
float aspect = (GLfloat)windowWidth/(GLfloat)windowHeight;
|
||||
double top = 0.1f*tan(45.0f*PI / 360.0);
|
||||
double right = top*aspect;
|
||||
|
||||
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
|
||||
glLoadIdentity(); // Reset current matrix (MODELVIEW)
|
||||
rlMatrixMode(RL_MODELVIEW); // Switch back to modelview matrix
|
||||
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
|
||||
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
|
||||
glLoadIdentity(); // Reset current matrix (MODELVIEW)
|
||||
rlMatrixMode(RL_MODELVIEW); // Get back to modelview matrix
|
||||
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
|
||||
|
@ -306,7 +378,7 @@ void SetTargetFPS(int 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
|
||||
|
@ -374,18 +446,18 @@ Color Fade(Color color, float alpha)
|
|||
// Detect if a key has been pressed once
|
||||
bool IsKeyPressed(int key)
|
||||
{
|
||||
bool ret = false;
|
||||
bool pressed = false;
|
||||
|
||||
currentKeyState[key] = IsKeyDown(key);
|
||||
|
||||
if (currentKeyState[key] != previousKeyState[key])
|
||||
{
|
||||
if (currentKeyState[key]) ret = true;
|
||||
if (currentKeyState[key]) pressed = true;
|
||||
previousKeyState[key] = currentKeyState[key];
|
||||
}
|
||||
else ret = false;
|
||||
else pressed = false;
|
||||
|
||||
return ret;
|
||||
return pressed;
|
||||
}
|
||||
|
||||
// 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
|
||||
bool IsKeyReleased(int key)
|
||||
{
|
||||
bool ret = false;
|
||||
bool released = false;
|
||||
|
||||
currentKeyState[key] = IsKeyUp(key);
|
||||
|
||||
if (currentKeyState[key] != previousKeyState[key])
|
||||
{
|
||||
if (currentKeyState[key]) ret = true;
|
||||
if (currentKeyState[key]) released = true;
|
||||
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)
|
||||
|
@ -422,18 +494,18 @@ bool IsKeyUp(int key)
|
|||
// Detect if a mouse button has been pressed once
|
||||
bool IsMouseButtonPressed(int button)
|
||||
{
|
||||
bool ret = false;
|
||||
bool pressed = false;
|
||||
|
||||
currentMouseState[button] = IsMouseButtonDown(button);
|
||||
|
||||
if (currentMouseState[button] != previousMouseState[button])
|
||||
{
|
||||
if (currentMouseState[button]) ret = true;
|
||||
if (currentMouseState[button]) pressed = true;
|
||||
previousMouseState[button] = currentMouseState[button];
|
||||
}
|
||||
else ret = false;
|
||||
else pressed = false;
|
||||
|
||||
return ret;
|
||||
return 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
|
||||
bool IsMouseButtonReleased(int button)
|
||||
{
|
||||
bool ret = false;
|
||||
bool released = false;
|
||||
|
||||
currentMouseState[button] = IsMouseButtonUp(button);
|
||||
|
||||
if (currentMouseState[button] != previousMouseState[button])
|
||||
{
|
||||
if (currentMouseState[button]) ret = true;
|
||||
if (currentMouseState[button]) released = true;
|
||||
previousMouseState[button] = currentMouseState[button];
|
||||
}
|
||||
else ret = false;
|
||||
else released = false;
|
||||
|
||||
return ret;
|
||||
return released;
|
||||
}
|
||||
|
||||
// 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
|
||||
bool IsGamepadButtonPressed(int gamepad, int button)
|
||||
{
|
||||
bool ret = false;
|
||||
bool pressed = false;
|
||||
|
||||
currentGamepadState[button] = IsGamepadButtonDown(gamepad, button);
|
||||
|
||||
if (currentGamepadState[button] != previousGamepadState[button])
|
||||
{
|
||||
if (currentGamepadState[button]) ret = true;
|
||||
if (currentGamepadState[button]) pressed = true;
|
||||
previousGamepadState[button] = currentGamepadState[button];
|
||||
}
|
||||
else ret = false;
|
||||
else pressed = false;
|
||||
|
||||
return ret;
|
||||
return pressed;
|
||||
}
|
||||
|
||||
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
|
||||
bool IsGamepadButtonReleased(int gamepad, int button)
|
||||
{
|
||||
bool ret = false;
|
||||
bool released = false;
|
||||
|
||||
currentGamepadState[button] = IsGamepadButtonUp(gamepad, button);
|
||||
|
||||
if (currentGamepadState[button] != previousGamepadState[button])
|
||||
{
|
||||
if (currentGamepadState[button]) ret = true;
|
||||
if (currentGamepadState[button]) released = true;
|
||||
previousGamepadState[button] = currentGamepadState[button];
|
||||
}
|
||||
else ret = false;
|
||||
else released = false;
|
||||
|
||||
return ret;
|
||||
return released;
|
||||
}
|
||||
|
||||
bool IsGamepadButtonUp(int gamepad, int button)
|
||||
|
@ -612,8 +684,7 @@ bool IsGamepadButtonUp(int gamepad, int button)
|
|||
// GLFW3 Error Callback, runs on GLFW3 error
|
||||
static void ErrorCallback(int error, const char *description)
|
||||
{
|
||||
printf(description);
|
||||
//fprintf(stderr, description);
|
||||
TraceLog(WARNING, "GLFW3 Error: %s", description);
|
||||
}
|
||||
|
||||
// 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
|
||||
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;
|
||||
|
||||
glfwGetFramebufferSize(window, &fbWidth, &fbHeight); // Get framebuffer size of current window
|
||||
|
||||
glViewport(0, 0, fbWidth, fbHeight); // Set viewport width and height
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear used buffers, depth buffer is used for 3D
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 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
|
||||
// If window is resized, graphics device is re-initialized
|
||||
// NOTE: Aspect ratio does not change, so, image can be deformed
|
||||
rlglInitGraphicsDevice(fbWidth, fbHeight);
|
||||
}
|
||||
|
||||
// Takes a bitmap (BMP) screenshot and saves it in the same folder as executable
|
||||
static void TakeScreenshot()
|
||||
{
|
||||
static int shotNum = 0; // Screenshot number, increments every screenshot take during program execution
|
||||
|
||||
|
||||
char buffer[20]; // Buffer to store file name
|
||||
int fbWidth, fbHeight;
|
||||
|
||||
unsigned char *imgData; // Pixel image data array
|
||||
int fbWidth, fbHeight; // Frame buffer width and height
|
||||
|
||||
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);
|
||||
|
||||
// NOTE: BMP directly stores data flipped vertically
|
||||
//WriteBitmap(buffer, imgDataPixel, fbWidth, fbHeight); // Writes pixel data array into a bitmap (BMP) file
|
||||
WritePNG(buffer, imgDataFlip, fbWidth, fbHeight);
|
||||
|
||||
free(imgDataFlip);
|
||||
|
||||
WritePNG(buffer, imgData, fbWidth, fbHeight);
|
||||
|
||||
free(imgData);
|
||||
|
||||
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
|
||||
*
|
||||
* Features:
|
||||
* Library written in plain C code (C99)
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* Used external libs:
|
||||
|
@ -23,8 +25,9 @@
|
|||
* 32bit Textures - All loaded images are converted automatically to RGBA textures
|
||||
* SpriteFonts - All loaded sprite-font images are converted to RGBA and POT textures
|
||||
* 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,
|
||||
* BSD-like license that allows static linking with closed source software:
|
||||
|
@ -51,6 +54,8 @@
|
|||
#ifndef RAYLIB_H
|
||||
#define RAYLIB_H
|
||||
|
||||
#include "stb_vorbis.h"
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Some basic Defines
|
||||
//----------------------------------------------------------------------------------
|
||||
|
@ -150,6 +155,19 @@
|
|||
// Boolean type
|
||||
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)
|
||||
typedef struct Color {
|
||||
unsigned char r;
|
||||
|
@ -182,29 +200,6 @@ typedef struct Texture2D {
|
|||
int height;
|
||||
} 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
|
||||
typedef struct Camera {
|
||||
Vector3 position;
|
||||
|
@ -212,20 +207,42 @@ typedef struct Camera {
|
|||
Vector3 up;
|
||||
} Camera;
|
||||
|
||||
// Basic 3d Model type
|
||||
typedef struct Model {
|
||||
int numVertices;
|
||||
Vector3 *vertices;
|
||||
Vector2 *texcoords;
|
||||
Vector3 *normals;
|
||||
} Model;
|
||||
typedef struct Character Character;
|
||||
|
||||
// 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 {
|
||||
unsigned int source;
|
||||
unsigned int buffer;
|
||||
} 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
|
||||
extern "C" { // Prevents name mangling of functions
|
||||
#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 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 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 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 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 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 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...
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
|
@ -389,13 +408,18 @@ void CloseAudioDevice(); // Close the aud
|
|||
Sound LoadSound(char *fileName); // Load sound to memory
|
||||
Sound LoadSoundFromRES(const char *rresName, int resId); // Load sound to memory from rRES file (raylib Resource)
|
||||
void UnloadSound(Sound sound); // Unload sound
|
||||
Music LoadMusic(char *fileName);
|
||||
void UnloadMusic(Music music);
|
||||
|
||||
void PlaySound(Sound sound); // Play a sound
|
||||
void PauseSound(Sound sound); // Pause 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 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
|
||||
}
|
||||
|
|
548
src/raymath.c
548
src/raymath.c
|
@ -199,6 +199,28 @@ Vector3 VectorReflect(Vector3 vector, Vector3 normal)
|
|||
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
|
||||
//----------------------------------------------------------------------------------
|
||||
|
@ -234,17 +256,17 @@ float MatrixDeterminant(Matrix mat)
|
|||
float result;
|
||||
|
||||
// Cache the matrix values (speed optimization)
|
||||
float a00 = mat.m0, a01 = mat.m1, a02 = mat.m2, a03 = mat.m3;
|
||||
float a10 = mat.m4, a11 = mat.m5, a12 = mat.m6, a13 = mat.m7;
|
||||
float a20 = mat.m8, a21 = mat.m9, a22 = mat.m10, a23 = mat.m11;
|
||||
float a30 = mat.m12, a31 = mat.m13, a32 = mat.m14, a33 = mat.m15;
|
||||
float a00 = mat.m0, a01 = mat.m1, a02 = mat.m2, a03 = mat.m3;
|
||||
float a10 = mat.m4, a11 = mat.m5, a12 = mat.m6, a13 = mat.m7;
|
||||
float a20 = mat.m8, a21 = mat.m9, a22 = mat.m10, a23 = mat.m11;
|
||||
float a30 = mat.m12, a31 = mat.m13, a32 = mat.m14, a33 = mat.m15;
|
||||
|
||||
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 +
|
||||
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 +
|
||||
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;
|
||||
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 +
|
||||
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 +
|
||||
a10*a01*a32*a23 - a00*a11*a32*a23 - a20*a11*a02*a33 + a10*a21*a02*a33 +
|
||||
a20*a01*a12*a33 - a00*a21*a12*a33 - a10*a01*a22*a33 + a00*a11*a22*a33;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -261,21 +283,21 @@ void MatrixTranspose(Matrix *mat)
|
|||
Matrix temp;
|
||||
|
||||
temp.m0 = mat->m0;
|
||||
temp.m1 = mat->m4;
|
||||
temp.m2 = mat->m8;
|
||||
temp.m3 = mat->m12;
|
||||
temp.m4 = mat->m1;
|
||||
temp.m5 = mat->m5;
|
||||
temp.m6 = mat->m9;
|
||||
temp.m7 = mat->m13;
|
||||
temp.m8 = mat->m2;
|
||||
temp.m9 = mat->m6;
|
||||
temp.m10 = mat->m10;
|
||||
temp.m11 = mat->m14;
|
||||
temp.m12 = mat->m3;
|
||||
temp.m13 = mat->m7;
|
||||
temp.m14 = mat->m11;
|
||||
temp.m15 = mat->m15;
|
||||
temp.m1 = mat->m4;
|
||||
temp.m2 = mat->m8;
|
||||
temp.m3 = mat->m12;
|
||||
temp.m4 = mat->m1;
|
||||
temp.m5 = mat->m5;
|
||||
temp.m6 = mat->m9;
|
||||
temp.m7 = mat->m13;
|
||||
temp.m8 = mat->m2;
|
||||
temp.m9 = mat->m6;
|
||||
temp.m10 = mat->m10;
|
||||
temp.m11 = mat->m14;
|
||||
temp.m12 = mat->m3;
|
||||
temp.m13 = mat->m7;
|
||||
temp.m14 = mat->m11;
|
||||
temp.m15 = mat->m15;
|
||||
|
||||
*mat = temp;
|
||||
}
|
||||
|
@ -285,50 +307,50 @@ void MatrixInvert(Matrix *mat)
|
|||
{
|
||||
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 a10 = mat->m4, a11 = mat->m5, a12 = mat->m6, a13 = mat->m7;
|
||||
float a20 = mat->m8, a21 = mat->m9, a22 = mat->m10, a23 = mat->m11;
|
||||
float a30 = mat->m12, a31 = mat->m13, a32 = mat->m14, a33 = mat->m15;
|
||||
|
||||
float b00 = a00*a11 - a01*a10;
|
||||
float b01 = a00*a12 - a02*a10;
|
||||
float b02 = a00*a13 - a03*a10;
|
||||
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;
|
||||
float a10 = mat->m4, a11 = mat->m5, a12 = mat->m6, a13 = mat->m7;
|
||||
float a20 = mat->m8, a21 = mat->m9, a22 = mat->m10, a23 = mat->m11;
|
||||
float a30 = mat->m12, a31 = mat->m13, a32 = mat->m14, a33 = mat->m15;
|
||||
|
||||
// Calculate the invert determinant (inlined to avoid double-caching)
|
||||
float invDet = 1/(b00*b11 - b01*b10 + b02*b09 + b03*b08 - b04*b07 + b05*b06);
|
||||
float 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 invDet = 1/(b00*b11 - b01*b10 + b02*b09 + b03*b08 - b04*b07 + b05*b06);
|
||||
|
||||
printf("%f\n", invDet);
|
||||
|
||||
temp.m0 = (a11*b11 - a12*b10 + a13*b09)*invDet;
|
||||
temp.m1 = (-a01*b11 + a02*b10 - a03*b09)*invDet;
|
||||
temp.m2 = (a31*b05 - a32*b04 + a33*b03)*invDet;
|
||||
temp.m3 = (-a21*b05 + a22*b04 - a23*b03)*invDet;
|
||||
temp.m4 = (-a10*b11 + a12*b08 - a13*b07)*invDet;
|
||||
temp.m5 = (a00*b11 - a02*b08 + a03*b07)*invDet;
|
||||
temp.m6 = (-a30*b05 + a32*b02 - a33*b01)*invDet;
|
||||
temp.m7 = (a20*b05 - a22*b02 + a23*b01)*invDet;
|
||||
temp.m8 = (a10*b10 - a11*b08 + a13*b06)*invDet;
|
||||
temp.m9 = (-a00*b10 + a01*b08 - a03*b06)*invDet;
|
||||
temp.m10 = (a30*b04 - a31*b02 + a33*b00)*invDet;
|
||||
temp.m11 = (-a20*b04 + a21*b02 - a23*b00)*invDet;
|
||||
temp.m12 = (-a10*b09 + a11*b07 - a12*b06)*invDet;
|
||||
temp.m13 = (a00*b09 - a01*b07 + a02*b06)*invDet;
|
||||
temp.m14 = (-a30*b03 + a31*b01 - a32*b00)*invDet;
|
||||
temp.m15 = (a20*b03 - a21*b01 + a22*b00)*invDet;
|
||||
|
||||
temp.m0 = (a11*b11 - a12*b10 + a13*b09)*invDet;
|
||||
temp.m1 = (-a01*b11 + a02*b10 - a03*b09)*invDet;
|
||||
temp.m2 = (a31*b05 - a32*b04 + a33*b03)*invDet;
|
||||
temp.m3 = (-a21*b05 + a22*b04 - a23*b03)*invDet;
|
||||
temp.m4 = (-a10*b11 + a12*b08 - a13*b07)*invDet;
|
||||
temp.m5 = (a00*b11 - a02*b08 + a03*b07)*invDet;
|
||||
temp.m6 = (-a30*b05 + a32*b02 - a33*b01)*invDet;
|
||||
temp.m7 = (a20*b05 - a22*b02 + a23*b01)*invDet;
|
||||
temp.m8 = (a10*b10 - a11*b08 + a13*b06)*invDet;
|
||||
temp.m9 = (-a00*b10 + a01*b08 - a03*b06)*invDet;
|
||||
temp.m10 = (a30*b04 - a31*b02 + a33*b00)*invDet;
|
||||
temp.m11 = (-a20*b04 + a21*b02 - a23*b00)*invDet;
|
||||
temp.m12 = (-a10*b09 + a11*b07 - a12*b06)*invDet;
|
||||
temp.m13 = (a00*b09 - a01*b07 + a02*b06)*invDet;
|
||||
temp.m14 = (-a30*b03 + a31*b01 - a32*b00)*invDet;
|
||||
temp.m15 = (a20*b03 - a21*b01 + a22*b00)*invDet;
|
||||
|
||||
PrintMatrix(temp);
|
||||
|
||||
*mat = temp;
|
||||
|
||||
*mat = temp;
|
||||
}
|
||||
|
||||
// Normalize provided matrix
|
||||
|
@ -337,21 +359,21 @@ void MatrixNormalize(Matrix *mat)
|
|||
float det = MatrixDeterminant(*mat);
|
||||
|
||||
mat->m0 /= det;
|
||||
mat->m1 /= det;
|
||||
mat->m2 /= det;
|
||||
mat->m3 /= det;
|
||||
mat->m4 /= det;
|
||||
mat->m5 /= det;
|
||||
mat->m6 /= det;
|
||||
mat->m7 /= det;
|
||||
mat->m8 /= det;
|
||||
mat->m9 /= det;
|
||||
mat->m10 /= det;
|
||||
mat->m11 /= det;
|
||||
mat->m12 /= det;
|
||||
mat->m13 /= det;
|
||||
mat->m14 /= det;
|
||||
mat->m15 /= det;
|
||||
mat->m1 /= det;
|
||||
mat->m2 /= det;
|
||||
mat->m3 /= det;
|
||||
mat->m4 /= det;
|
||||
mat->m5 /= det;
|
||||
mat->m6 /= det;
|
||||
mat->m7 /= det;
|
||||
mat->m8 /= det;
|
||||
mat->m9 /= det;
|
||||
mat->m10 /= det;
|
||||
mat->m11 /= det;
|
||||
mat->m12 /= det;
|
||||
mat->m13 /= det;
|
||||
mat->m14 /= det;
|
||||
mat->m15 /= det;
|
||||
}
|
||||
|
||||
// Returns identity matrix
|
||||
|
@ -368,21 +390,21 @@ Matrix MatrixAdd(Matrix left, Matrix right)
|
|||
Matrix result = MatrixIdentity();
|
||||
|
||||
result.m0 = left.m0 + right.m0;
|
||||
result.m1 = left.m1 + right.m1;
|
||||
result.m2 = left.m2 + right.m2;
|
||||
result.m3 = left.m3 + right.m3;
|
||||
result.m4 = left.m4 + right.m4;
|
||||
result.m5 = left.m5 + right.m5;
|
||||
result.m6 = left.m6 + right.m6;
|
||||
result.m7 = left.m7 + right.m7;
|
||||
result.m8 = left.m8 + right.m8;
|
||||
result.m9 = left.m9 + right.m9;
|
||||
result.m10 = left.m10 + right.m10;
|
||||
result.m11 = left.m11 + right.m11;
|
||||
result.m12 = left.m12 + right.m12;
|
||||
result.m13 = left.m13 + right.m13;
|
||||
result.m14 = left.m14 + right.m14;
|
||||
result.m15 = left.m15 + right.m15;
|
||||
result.m1 = left.m1 + right.m1;
|
||||
result.m2 = left.m2 + right.m2;
|
||||
result.m3 = left.m3 + right.m3;
|
||||
result.m4 = left.m4 + right.m4;
|
||||
result.m5 = left.m5 + right.m5;
|
||||
result.m6 = left.m6 + right.m6;
|
||||
result.m7 = left.m7 + right.m7;
|
||||
result.m8 = left.m8 + right.m8;
|
||||
result.m9 = left.m9 + right.m9;
|
||||
result.m10 = left.m10 + right.m10;
|
||||
result.m11 = left.m11 + right.m11;
|
||||
result.m12 = left.m12 + right.m12;
|
||||
result.m13 = left.m13 + right.m13;
|
||||
result.m14 = left.m14 + right.m14;
|
||||
result.m15 = left.m15 + right.m15;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -393,21 +415,21 @@ Matrix MatrixSubstract(Matrix left, Matrix right)
|
|||
Matrix result = MatrixIdentity();
|
||||
|
||||
result.m0 = left.m0 - right.m0;
|
||||
result.m1 = left.m1 - right.m1;
|
||||
result.m2 = left.m2 - right.m2;
|
||||
result.m3 = left.m3 - right.m3;
|
||||
result.m4 = left.m4 - right.m4;
|
||||
result.m5 = left.m5 - right.m5;
|
||||
result.m6 = left.m6 - right.m6;
|
||||
result.m7 = left.m7 - right.m7;
|
||||
result.m8 = left.m8 - right.m8;
|
||||
result.m9 = left.m9 - right.m9;
|
||||
result.m10 = left.m10 - right.m10;
|
||||
result.m11 = left.m11 - right.m11;
|
||||
result.m12 = left.m12 - right.m12;
|
||||
result.m13 = left.m13 - right.m13;
|
||||
result.m14 = left.m14 - right.m14;
|
||||
result.m15 = left.m15 - right.m15;
|
||||
result.m1 = left.m1 - right.m1;
|
||||
result.m2 = left.m2 - right.m2;
|
||||
result.m3 = left.m3 - right.m3;
|
||||
result.m4 = left.m4 - right.m4;
|
||||
result.m5 = left.m5 - right.m5;
|
||||
result.m6 = left.m6 - right.m6;
|
||||
result.m7 = left.m7 - right.m7;
|
||||
result.m8 = left.m8 - right.m8;
|
||||
result.m9 = left.m9 - right.m9;
|
||||
result.m10 = left.m10 - right.m10;
|
||||
result.m11 = left.m11 - right.m11;
|
||||
result.m12 = left.m12 - right.m12;
|
||||
result.m13 = left.m13 - right.m13;
|
||||
result.m14 = left.m14 - right.m14;
|
||||
result.m15 = left.m15 - right.m15;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -476,51 +498,51 @@ Matrix MatrixFromAxisAngle(Vector3 axis, float angle)
|
|||
|
||||
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;
|
||||
x *= length;
|
||||
y *= length;
|
||||
z *= length;
|
||||
}
|
||||
|
||||
float s = sin(angle);
|
||||
float c = cos(angle);
|
||||
float t = 1-c;
|
||||
|
||||
// Cache some matrix values (speed optimization)
|
||||
float a00 = mat.m0, a01 = mat.m1, a02 = mat.m2, a03 = mat.m3;
|
||||
float a10 = mat.m4, a11 = mat.m5, a12 = mat.m6, a13 = mat.m7;
|
||||
float a20 = mat.m8, a21 = mat.m9, a22 = mat.m10, a23 = mat.m11;
|
||||
|
||||
// Construct the elements of the rotation matrix
|
||||
float b00 = x*x*t + c, b01 = y*x*t + z*s, b02 = z*x*t - y*s;
|
||||
float b10 = x*y*t - z*s, b11 = y*y*t + c, b12 = z*y*t + x*s;
|
||||
float b20 = x*z*t + y*s, b21 = y*z*t - x*s, b22 = z*z*t + c;
|
||||
|
||||
// Perform rotation-specific matrix multiplication
|
||||
result.m0 = a00*b00 + a10*b01 + a20*b02;
|
||||
result.m1 = a01*b00 + a11*b01 + a21*b02;
|
||||
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;
|
||||
length = 1 / length;
|
||||
x *= length;
|
||||
y *= length;
|
||||
z *= length;
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -645,35 +667,35 @@ Matrix MatrixMultiply(Matrix left, Matrix right)
|
|||
{
|
||||
Matrix result;
|
||||
|
||||
// Cache the matrix values (speed optimization)
|
||||
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 a20 = left.m8, a21 = left.m9, a22 = left.m10, a23 = left.m11;
|
||||
float a30 = left.m12, a31 = left.m13, a32 = left.m14, a33 = left.m15;
|
||||
|
||||
float b00 = right.m0, b01 = right.m1, b02 = right.m2, b03 = right.m3;
|
||||
float b10 = right.m4, b11 = right.m5, b12 = right.m6, b13 = right.m7;
|
||||
float b20 = right.m8, b21 = right.m9, b22 = right.m10, b23 = right.m11;
|
||||
float b30 = right.m12, b31 = right.m13, b32 = right.m14, b33 = right.m15;
|
||||
|
||||
result.m0 = b00*a00 + b01*a10 + b02*a20 + b03*a30;
|
||||
result.m1 = b00*a01 + b01*a11 + b02*a21 + b03*a31;
|
||||
result.m2 = b00*a02 + b01*a12 + b02*a22 + b03*a32;
|
||||
result.m3 = b00*a03 + b01*a13 + b02*a23 + b03*a33;
|
||||
result.m4 = b10*a00 + b11*a10 + b12*a20 + b13*a30;
|
||||
result.m5 = b10*a01 + b11*a11 + b12*a21 + b13*a31;
|
||||
result.m6 = b10*a02 + b11*a12 + b12*a22 + b13*a32;
|
||||
result.m7 = b10*a03 + b11*a13 + b12*a23 + b13*a33;
|
||||
result.m8 = b20*a00 + b21*a10 + b22*a20 + b23*a30;
|
||||
result.m9 = b20*a01 + b21*a11 + b22*a21 + b23*a31;
|
||||
result.m10 = b20*a02 + b21*a12 + b22*a22 + b23*a32;
|
||||
result.m11 = b20*a03 + b21*a13 + b22*a23 + b23*a33;
|
||||
result.m12 = b30*a00 + b31*a10 + b32*a20 + b33*a30;
|
||||
result.m13 = b30*a01 + b31*a11 + b32*a21 + b33*a31;
|
||||
result.m14 = b30*a02 + b31*a12 + b32*a22 + b33*a32;
|
||||
result.m15 = b30*a03 + b31*a13 + b32*a23 + b33*a33;
|
||||
|
||||
return result;
|
||||
// Cache the matrix values (speed optimization)
|
||||
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 a20 = left.m8, a21 = left.m9, a22 = left.m10, a23 = left.m11;
|
||||
float a30 = left.m12, a31 = left.m13, a32 = left.m14, a33 = left.m15;
|
||||
|
||||
float b00 = right.m0, b01 = right.m1, b02 = right.m2, b03 = right.m3;
|
||||
float b10 = right.m4, b11 = right.m5, b12 = right.m6, b13 = right.m7;
|
||||
float b20 = right.m8, b21 = right.m9, b22 = right.m10, b23 = right.m11;
|
||||
float b30 = right.m12, b31 = right.m13, b32 = right.m14, b33 = right.m15;
|
||||
|
||||
result.m0 = b00*a00 + b01*a10 + b02*a20 + b03*a30;
|
||||
result.m1 = b00*a01 + b01*a11 + b02*a21 + b03*a31;
|
||||
result.m2 = b00*a02 + b01*a12 + b02*a22 + b03*a32;
|
||||
result.m3 = b00*a03 + b01*a13 + b02*a23 + b03*a33;
|
||||
result.m4 = b10*a00 + b11*a10 + b12*a20 + b13*a30;
|
||||
result.m5 = b10*a01 + b11*a11 + b12*a21 + b13*a31;
|
||||
result.m6 = b10*a02 + b11*a12 + b12*a22 + b13*a32;
|
||||
result.m7 = b10*a03 + b11*a13 + b12*a23 + b13*a33;
|
||||
result.m8 = b20*a00 + b21*a10 + b22*a20 + b23*a30;
|
||||
result.m9 = b20*a01 + b21*a11 + b22*a21 + b23*a31;
|
||||
result.m10 = b20*a02 + b21*a12 + b22*a22 + b23*a32;
|
||||
result.m11 = b20*a03 + b21*a13 + b22*a23 + b23*a33;
|
||||
result.m12 = b30*a00 + b31*a10 + b32*a20 + b33*a30;
|
||||
result.m13 = b30*a01 + b31*a11 + b32*a21 + b33*a31;
|
||||
result.m14 = b30*a02 + b31*a12 + b32*a22 + b33*a32;
|
||||
result.m15 = b30*a03 + b31*a13 + b32*a23 + b33*a33;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Returns perspective projection matrix
|
||||
|
@ -681,28 +703,28 @@ Matrix MatrixFrustum(double left, double right, double bottom, double top, doubl
|
|||
{
|
||||
Matrix result;
|
||||
|
||||
float rl = (right - left);
|
||||
float tb = (top - bottom);
|
||||
float fn = (far - near);
|
||||
float rl = (right - left);
|
||||
float tb = (top - bottom);
|
||||
float fn = (far - near);
|
||||
|
||||
result.m0 = (near*2) / rl;
|
||||
result.m1 = 0;
|
||||
result.m2 = 0;
|
||||
result.m3 = 0;
|
||||
result.m4 = 0;
|
||||
result.m5 = (near*2) / tb;
|
||||
result.m6 = 0;
|
||||
result.m7 = 0;
|
||||
result.m8 = (right + left) / rl;
|
||||
result.m9 = (top + bottom) / tb;
|
||||
result.m10 = -(far + near) / fn;
|
||||
result.m11 = -1;
|
||||
result.m12 = 0;
|
||||
result.m13 = 0;
|
||||
result.m14 = -(far*near*2) / fn;
|
||||
result.m15 = 0;
|
||||
result.m0 = (near*2) / rl;
|
||||
result.m1 = 0;
|
||||
result.m2 = 0;
|
||||
result.m3 = 0;
|
||||
result.m4 = 0;
|
||||
result.m5 = (near*2) / tb;
|
||||
result.m6 = 0;
|
||||
result.m7 = 0;
|
||||
result.m8 = (right + left) / rl;
|
||||
result.m9 = (top + bottom) / tb;
|
||||
result.m10 = -(far + near) / fn;
|
||||
result.m11 = -1;
|
||||
result.m12 = 0;
|
||||
result.m13 = 0;
|
||||
result.m14 = -(far*near*2) / fn;
|
||||
result.m15 = 0;
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Returns perspective projection matrix
|
||||
|
@ -720,25 +742,25 @@ Matrix MatrixOrtho(double left, double right, double bottom, double top, double
|
|||
Matrix result;
|
||||
|
||||
float rl = (right - left);
|
||||
float tb = (top - bottom);
|
||||
float fn = (far - near);
|
||||
|
||||
float tb = (top - bottom);
|
||||
float fn = (far - near);
|
||||
|
||||
result.m0 = 2 / rl;
|
||||
result.m1 = 0;
|
||||
result.m2 = 0;
|
||||
result.m3 = 0;
|
||||
result.m4 = 0;
|
||||
result.m5 = 2 / tb;
|
||||
result.m6 = 0;
|
||||
result.m7 = 0;
|
||||
result.m8 = 0;
|
||||
result.m9 = 0;
|
||||
result.m10 = -2 / fn;
|
||||
result.m11 = 0;
|
||||
result.m12 = -(left + right) / rl;
|
||||
result.m13 = -(top + bottom) / tb;
|
||||
result.m14 = -(far + near) / fn;
|
||||
result.m15 = 1;
|
||||
result.m1 = 0;
|
||||
result.m2 = 0;
|
||||
result.m3 = 0;
|
||||
result.m4 = 0;
|
||||
result.m5 = 2 / tb;
|
||||
result.m6 = 0;
|
||||
result.m7 = 0;
|
||||
result.m8 = 0;
|
||||
result.m9 = 0;
|
||||
result.m10 = -2 / fn;
|
||||
result.m11 = 0;
|
||||
result.m12 = -(left + right) / rl;
|
||||
result.m13 = -(top + bottom) / tb;
|
||||
result.m14 = -(far + near) / fn;
|
||||
result.m15 = 1;
|
||||
|
||||
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 result;
|
||||
|
||||
|
||||
Vector3 z = VectorSubtract(eye, target);
|
||||
VectorNormalize(&z);
|
||||
Vector3 x = VectorCrossProduct(up, z);
|
||||
|
@ -793,7 +815,7 @@ void PrintMatrix(Matrix m)
|
|||
// Calculates the length of a quaternion
|
||||
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
|
||||
|
@ -818,15 +840,15 @@ Quaternion QuaternionMultiply(Quaternion q1, Quaternion q2)
|
|||
{
|
||||
Quaternion result;
|
||||
|
||||
float qax = q1.x, qay = q1.y, qaz = q1.z, qaw = q1.w;
|
||||
float qbx = q2.x, qby = q2.y, qbz = q2.z, qbw = q2.w;
|
||||
|
||||
result.x = qax*qbw + qaw*qbx + qay*qbz - qaz*qby;
|
||||
result.y = qay*qbw + qaw*qby + qaz*qbx - qax*qbz;
|
||||
result.z = qaz*qbw + qaw*qbz + qax*qby - qay*qbx;
|
||||
result.w = qaw*qbw - qax*qbx - qay*qby - qaz*qbz;
|
||||
|
||||
return result;
|
||||
float qax = q1.x, qay = q1.y, qaz = q1.z, qaw = q1.w;
|
||||
float qbx = q2.x, qby = q2.y, qbz = q2.z, qbw = q2.w;
|
||||
|
||||
result.x = qax*qbw + qaw*qbx + qay*qbz - qaz*qby;
|
||||
result.y = qay*qbw + qaw*qby + qaz*qbx - qax*qbz;
|
||||
result.z = qaz*qbw + qaw*qbz + qax*qby - qay*qbx;
|
||||
result.w = qaw*qbw - qax*qbx - qay*qby - qaz*qbz;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Calculates spherical linear interpolation between two quaternions
|
||||
|
@ -834,9 +856,9 @@ Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float amount)
|
|||
{
|
||||
Quaternion result;
|
||||
|
||||
float cosHalfTheta = q1.x*q2.x + q1.y*q2.y + q1.z*q2.z + q1.w*q2.w;
|
||||
|
||||
if (abs(cosHalfTheta) >= 1.0) result = q1;
|
||||
float cosHalfTheta = q1.x*q2.x + q1.y*q2.y + q1.z*q2.z + q1.w*q2.w;
|
||||
|
||||
if (abs(cosHalfTheta) >= 1.0) result = q1;
|
||||
else
|
||||
{
|
||||
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.w = (q1.w*ratioA + q2.w*ratioB);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Returns a quaternion from a given rotation matrix
|
||||
|
@ -947,42 +969,42 @@ Matrix QuaternionToMatrix(Quaternion q)
|
|||
{
|
||||
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 y2 = y + y;
|
||||
float z2 = z + z;
|
||||
float x2 = x + x;
|
||||
float y2 = y + y;
|
||||
float z2 = z + z;
|
||||
|
||||
float xx = x*x2;
|
||||
float xy = x*y2;
|
||||
float xz = x*z2;
|
||||
float xx = x*x2;
|
||||
float xy = x*y2;
|
||||
float xz = x*z2;
|
||||
|
||||
float yy = y*y2;
|
||||
float yz = y*z2;
|
||||
float zz = z*z2;
|
||||
float yy = y*y2;
|
||||
float yz = y*z2;
|
||||
float zz = z*z2;
|
||||
|
||||
float wx = w*x2;
|
||||
float wy = w*y2;
|
||||
float wz = w*z2;
|
||||
float wx = w*x2;
|
||||
float wy = w*y2;
|
||||
float wz = w*z2;
|
||||
|
||||
result.m0 = 1 - (yy + zz);
|
||||
result.m1 = xy - wz;
|
||||
result.m2 = xz + wy;
|
||||
result.m3 = 0;
|
||||
result.m4 = xy + wz;
|
||||
result.m5 = 1 - (xx + zz);
|
||||
result.m6 = yz - wx;
|
||||
result.m7 = 0;
|
||||
result.m8 = xz - wy;
|
||||
result.m9 = yz + wx;
|
||||
result.m10 = 1 - (xx + yy);
|
||||
result.m11 = 0;
|
||||
result.m12 = 0;
|
||||
result.m13 = 0;
|
||||
result.m14 = 0;
|
||||
result.m15 = 1;
|
||||
|
||||
return result;
|
||||
result.m0 = 1 - (yy + zz);
|
||||
result.m1 = xy - wz;
|
||||
result.m2 = xz + wy;
|
||||
result.m3 = 0;
|
||||
result.m4 = xy + wz;
|
||||
result.m5 = 1 - (xx + zz);
|
||||
result.m6 = yz - wx;
|
||||
result.m7 = 0;
|
||||
result.m8 = xz - wy;
|
||||
result.m9 = yz + wx;
|
||||
result.m10 = 1 - (xx + yy);
|
||||
result.m11 = 0;
|
||||
result.m12 = 0;
|
||||
result.m13 = 0;
|
||||
result.m14 = 0;
|
||||
result.m15 = 1;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// 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
|
||||
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
|
||||
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
|
||||
|
|
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 <GL/gl.h> // OpenGL functions
|
||||
#include <stdlib.h> // Required for abs() function
|
||||
#include <math.h> // Math related functions, sin() and cos() used on DrawCircle*
|
||||
// sqrt() and pow() and abs() used on CheckCollision*
|
||||
|
||||
#include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3+ or ES2
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Defines and Macros
|
||||
|
@ -57,149 +58,108 @@
|
|||
// Draw a pixel
|
||||
void DrawPixel(int posX, int posY, Color color)
|
||||
{
|
||||
glBegin(GL_POINTS);
|
||||
glColor4ub(color.r, color.g, color.b, color.a);
|
||||
glVertex2i(posX, posY);
|
||||
glEnd();
|
||||
|
||||
// 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);
|
||||
*/
|
||||
rlBegin(RL_LINES);
|
||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
rlVertex2i(posX, posY);
|
||||
rlVertex2i(posX + 1, posY + 1);
|
||||
rlEnd();
|
||||
}
|
||||
|
||||
// Draw a pixel (Vector version)
|
||||
void DrawPixelV(Vector2 position, Color color)
|
||||
{
|
||||
glBegin(GL_POINTS);
|
||||
glColor4ub(color.r, color.g, color.b, color.a);
|
||||
glVertex2f(position.x, position.y);
|
||||
glEnd();
|
||||
rlBegin(RL_LINES);
|
||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
rlVertex2f(position.x, position.y);
|
||||
rlVertex2i(position.x + 1, position.y + 1);
|
||||
rlEnd();
|
||||
}
|
||||
|
||||
// Draw a line
|
||||
void DrawLine(int startPosX, int startPosY, int endPosX, int endPosY, Color color)
|
||||
{
|
||||
glBegin(GL_LINES);
|
||||
glColor4ub(color.r, color.g, color.b, color.a);
|
||||
glVertex2i(startPosX, startPosY);
|
||||
glVertex2i(endPosX, endPosY);
|
||||
glEnd();
|
||||
rlBegin(RL_LINES);
|
||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
rlVertex2i(startPosX, startPosY);
|
||||
rlVertex2i(endPosX, endPosY);
|
||||
rlEnd();
|
||||
}
|
||||
|
||||
// Draw a line (Vector version)
|
||||
void DrawLineV(Vector2 startPos, Vector2 endPos, Color color)
|
||||
{
|
||||
glBegin(GL_LINES);
|
||||
glColor4ub(color.r, color.g, color.b, color.a);
|
||||
glVertex2f(startPos.x, startPos.y);
|
||||
glVertex2f(endPos.x, endPos.y);
|
||||
glEnd();
|
||||
rlBegin(RL_LINES);
|
||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
rlVertex2f(startPos.x, startPos.y);
|
||||
rlVertex2f(endPos.x, endPos.y);
|
||||
rlEnd();
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
glEnable(GL_POLYGON_SMOOTH);
|
||||
glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); // Deprecated on OGL 3.0
|
||||
|
||||
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
|
||||
// NOTE: Gradient goes from center (color1) to border (color2)
|
||||
void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Color color2)
|
||||
{
|
||||
glBegin(GL_TRIANGLE_FAN);
|
||||
glColor4ub(color1.r, color1.g, color1.b, color1.a);
|
||||
glVertex2i(centerX, centerY);
|
||||
glColor4ub(color2.r, color2.g, color2.b, color2.a);
|
||||
|
||||
for (int i=0; i <= 360; i++) //i++ --> Step = 1.0 pixels
|
||||
rlBegin(RL_TRIANGLES);
|
||||
for (int i=0; i < 360; i += 2)
|
||||
{
|
||||
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)
|
||||
void DrawCircleV(Vector2 center, float radius, Color color)
|
||||
{
|
||||
glEnable(GL_POLYGON_SMOOTH);
|
||||
glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
|
||||
|
||||
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
|
||||
rlBegin(RL_TRIANGLES);
|
||||
for (int i=0; i < 360; i += 2)
|
||||
{
|
||||
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();
|
||||
|
||||
glDisable(GL_POLYGON_SMOOTH);
|
||||
rlEnd();
|
||||
}
|
||||
|
||||
// Draw circle outline
|
||||
void DrawCircleLines(int centerX, int centerY, float radius, Color color)
|
||||
{
|
||||
glEnable(GL_LINE_SMOOTH); // Smoothies circle outline (anti-aliasing applied)
|
||||
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); // Best quality for line smooth (anti-aliasing best algorithm)
|
||||
|
||||
glBegin(GL_LINE_LOOP);
|
||||
glColor4ub(color.r, color.g, color.b, color.a);
|
||||
rlBegin(RL_LINES);
|
||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
|
||||
// NOTE: Circle outline is drawn pixel by pixel every degree (0 to 360)
|
||||
for (int i=0; i < 360; i++)
|
||||
{
|
||||
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();
|
||||
|
||||
// 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);
|
||||
rlEnd();
|
||||
}
|
||||
|
||||
// Draw a color-filled rectangle
|
||||
void DrawRectangle(int posX, int posY, int width, int height, Color color)
|
||||
{
|
||||
glBegin(GL_QUADS);
|
||||
glColor4ub(color.r, color.g, color.b, color.a);
|
||||
glVertex2i(posX, posY);
|
||||
glVertex2i(posX + width, posY);
|
||||
glVertex2i(posX + width, posY + height);
|
||||
glVertex2i(posX, posY + height);
|
||||
glEnd();
|
||||
rlBegin(RL_QUADS);
|
||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
rlTexCoord2f(0.0f, 0.0f);
|
||||
rlVertex2i(posX, posY);
|
||||
rlTexCoord2f(0.0f, 1.0f);
|
||||
rlVertex2i(posX, posY + height);
|
||||
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
|
||||
|
@ -212,73 +172,73 @@ void DrawRectangleRec(Rectangle rec, Color color)
|
|||
// NOTE: Gradient goes from bottom (color1) to top (color2)
|
||||
void DrawRectangleGradient(int posX, int posY, int width, int height, Color color1, Color color2)
|
||||
{
|
||||
glBegin(GL_QUADS);
|
||||
glColor4ub(color1.r, color1.g, color1.b, color1.a);
|
||||
glVertex2i(posX, posY);
|
||||
glVertex2i(posX + width, posY);
|
||||
glColor4ub(color2.r, color2.g, color2.b, color2.a);
|
||||
glVertex2i(posX + width, posY + height);
|
||||
glVertex2i(posX, posY + height);
|
||||
glEnd();
|
||||
rlBegin(RL_QUADS);
|
||||
rlColor4ub(color1.r, color1.g, color1.b, color1.a);
|
||||
rlVertex2i(posX, posY);
|
||||
rlColor4ub(color1.r, color1.g, color1.b, color1.a);
|
||||
rlVertex2i(posX, posY + height);
|
||||
rlColor4ub(color2.r, color2.g, color2.b, color2.a);
|
||||
rlVertex2i(posX + width, posY + height);
|
||||
rlColor4ub(color2.r, color2.g, color2.b, color2.a);
|
||||
rlVertex2i(posX + width, posY);
|
||||
rlEnd();
|
||||
}
|
||||
|
||||
// Draw a color-filled rectangle (Vector version)
|
||||
void DrawRectangleV(Vector2 position, Vector2 size, Color color)
|
||||
{
|
||||
glBegin(GL_QUADS);
|
||||
glColor4ub(color.r, color.g, color.b, color.a);
|
||||
glVertex2i(position.x, position.y);
|
||||
glVertex2i(position.x + size.x, position.y);
|
||||
glVertex2i(position.x + size.x, position.y + size.y);
|
||||
glVertex2i(position.x, position.y + size.y);
|
||||
glEnd();
|
||||
rlBegin(RL_QUADS);
|
||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
rlVertex2i(position.x, position.y);
|
||||
rlVertex2i(position.x, position.y + size.y);
|
||||
rlVertex2i(position.x + size.x, position.y + size.y);
|
||||
rlVertex2i(position.x + size.x, position.y);
|
||||
rlEnd();
|
||||
}
|
||||
|
||||
// Draw rectangle outline
|
||||
void DrawRectangleLines(int posX, int posY, int width, int height, Color color)
|
||||
{
|
||||
//glEnable(GL_LINE_SMOOTH); // Smoothies circle outline (anti-aliasing applied)
|
||||
//glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); // Best quality for line smooth (anti-aliasing best algorithm)
|
||||
|
||||
// NOTE: Lines are rasterized using the "Diamond Exit" rule so, it's nearly impossible to obtain a pixel-perfect engine
|
||||
// NOTE: Recommended trying to avoid using lines, at least >1.0f pixel lines with anti-aliasing (glLineWidth function)
|
||||
|
||||
glBegin(GL_LINE_LOOP);
|
||||
glColor4ub(color.r, color.g, color.b, color.a);
|
||||
glVertex2i(posX, posY);
|
||||
glVertex2i(posX + width - 1, posY);
|
||||
glVertex2i(posX + width - 1, posY + height - 1);
|
||||
glVertex2i(posX, posY + height - 1);
|
||||
glEnd();
|
||||
|
||||
// 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);
|
||||
rlBegin(RL_LINES);
|
||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
rlVertex2i(posX, posY);
|
||||
rlVertex2i(posX + width - 1, posY);
|
||||
|
||||
rlVertex2i(posX + width - 1, posY);
|
||||
rlVertex2i(posX + width - 1, posY + height - 1);
|
||||
|
||||
rlVertex2i(posX + width - 1, posY + height - 1);
|
||||
rlVertex2i(posX, posY + height - 1);
|
||||
|
||||
rlVertex2i(posX, posY + height - 1);
|
||||
rlVertex2i(posX, posY);
|
||||
rlEnd();
|
||||
}
|
||||
|
||||
// Draw a triangle
|
||||
void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color)
|
||||
{
|
||||
glBegin(GL_TRIANGLES);
|
||||
glColor4ub(color.r, color.g, color.b, color.a);
|
||||
glVertex2f(v1.x, v1.y);
|
||||
glVertex2f(v2.x, v2.y);
|
||||
glVertex2f(v3.x, v3.y);
|
||||
glEnd();
|
||||
rlBegin(RL_TRIANGLES);
|
||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
rlVertex2f(v1.x, v1.y);
|
||||
rlVertex2f(v2.x, v2.y);
|
||||
rlVertex2f(v3.x, v3.y);
|
||||
rlEnd();
|
||||
}
|
||||
|
||||
void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color)
|
||||
{
|
||||
glBegin(GL_LINE_LOOP);
|
||||
glColor4ub(color.r, color.g, color.b, color.a);
|
||||
glVertex2f(v1.x, v1.y);
|
||||
glVertex2f(v2.x, v2.y);
|
||||
glVertex2f(v3.x, v3.y);
|
||||
glEnd();
|
||||
rlBegin(RL_LINES);
|
||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
rlVertex2f(v1.x, v1.y);
|
||||
rlVertex2f(v2.x, v2.y);
|
||||
|
||||
rlVertex2f(v2.x, v2.y);
|
||||
rlVertex2f(v3.x, v3.y);
|
||||
|
||||
rlVertex2f(v3.x, v3.y);
|
||||
rlVertex2f(v1.x, v1.y);
|
||||
rlEnd();
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(center.x, center.y, 0);
|
||||
glRotatef(rotation, 0, 0, 1);
|
||||
rlPushMatrix();
|
||||
rlTranslatef(center.x, center.y, 0.0);
|
||||
rlRotatef(rotation, 0, 0, 1);
|
||||
|
||||
glBegin(GL_TRIANGLE_FAN);
|
||||
glColor4ub(color.r, color.g, color.b, color.a);
|
||||
glVertex2f(0, 0);
|
||||
|
||||
for (int i=0; i <= sides; i++)
|
||||
{
|
||||
glVertex2f(radius*cos(i*2*PI/sides), radius*sin(i*2*PI/sides));
|
||||
rlBegin(RL_TRIANGLES);
|
||||
for (int i=0; i < 360; i += 360/sides)
|
||||
{
|
||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
|
||||
rlVertex2i(0, 0);
|
||||
rlVertex2f(sin(DEG2RAD*i) * radius, cos(DEG2RAD*i) * radius);
|
||||
rlVertex2f(sin(DEG2RAD*(i+360/sides)) * radius, cos(DEG2RAD*(i+360/sides)) * radius);
|
||||
}
|
||||
glEnd();
|
||||
glPopMatrix();
|
||||
rlEnd();
|
||||
rlPopMatrix();
|
||||
}
|
||||
|
||||
// Draw a closed polygon defined by points
|
||||
|
@ -308,19 +269,16 @@ void DrawPolyEx(Vector2 *points, int numPoints, Color color)
|
|||
{
|
||||
if (numPoints >= 3)
|
||||
{
|
||||
glEnable(GL_POLYGON_SMOOTH);
|
||||
glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
|
||||
|
||||
glBegin(GL_POLYGON);
|
||||
glColor4ub(color.r, color.g, color.b, color.a);
|
||||
rlBegin(RL_TRIANGLES);
|
||||
rlColor4ub(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();
|
||||
|
||||
glDisable(GL_POLYGON_SMOOTH);
|
||||
rlEnd();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -330,22 +288,22 @@ void DrawPolyExLines(Vector2 *points, int numPoints, Color color)
|
|||
{
|
||||
if (numPoints >= 2)
|
||||
{
|
||||
//glEnable(GL_LINE_SMOOTH); // Smoothies circle outline (anti-aliasing applied)
|
||||
//glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); // Best quality for line smooth (anti-aliasing best algorithm)
|
||||
|
||||
glBegin(GL_LINE_LOOP);
|
||||
glColor4ub(color.r, color.g, color.b, color.a);
|
||||
rlBegin(RL_LINES);
|
||||
rlColor4ub(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();
|
||||
|
||||
//glDisable(GL_LINE_SMOOTH);
|
||||
rlEnd();
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module Functions Definition - Collision Detection functions
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Check if point is inside rectangle
|
||||
bool CheckCollisionPointRec(Vector2 point, Rectangle rec)
|
||||
{
|
||||
|
|
|
@ -11,5 +11,4 @@ void main()
|
|||
{
|
||||
// Output pixel color
|
||||
pixelColor = texture(texture0, fragTexCoord) * fragColor;
|
||||
//pixelColor = fragColor;
|
||||
}
|
|
@ -11,6 +11,7 @@
|
|||
// Get the latest version and other information at:
|
||||
// http://nothings.org/stb_vorbis/
|
||||
|
||||
|
||||
// Todo:
|
||||
//
|
||||
// - seeking (note you can seek yourself using the pushdata API)
|
||||
|
@ -25,6 +26,9 @@
|
|||
//
|
||||
// All of these limitations may be removed in future versions.
|
||||
|
||||
|
||||
#include "stb_vorbis.h"
|
||||
|
||||
#ifndef STB_VORBIS_HEADER_ONLY
|
||||
|
||||
// global configuration settings (e.g. set these in the project/makefile),
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
// Get the latest version and other information at:
|
||||
// http://nothings.org/stb_vorbis/
|
||||
|
||||
|
||||
// Todo:
|
||||
//
|
||||
// - seeking (note you can seek yourself using the pushdata API)
|
||||
|
@ -25,12 +26,6 @@
|
|||
//
|
||||
// All of these limitations may be removed in future versions.
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// HEADER BEGINS HERE
|
||||
//
|
||||
|
||||
#ifndef STB_VORBIS_INCLUDE_STB_VORBIS_H
|
||||
#define STB_VORBIS_INCLUDE_STB_VORBIS_H
|
||||
|
||||
|
@ -349,4 +344,4 @@ enum STBVorbisError
|
|||
}
|
||||
#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 <GL/gl.h> // OpenGL functions
|
||||
#include <stdlib.h> // Declares malloc() and free() for memory management
|
||||
#include <string.h> // String management functions (just strlen() is used)
|
||||
#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 "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3+ or ES2
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Defines and Macros
|
||||
//----------------------------------------------------------------------------------
|
||||
|
@ -49,13 +50,22 @@
|
|||
typedef unsigned char byte;
|
||||
|
||||
// SpriteFont one Character (Glyph) data
|
||||
struct Character {
|
||||
typedef struct Character {
|
||||
int value; //char value = ' '; (int)value = 32;
|
||||
int x;
|
||||
int y;
|
||||
int w;
|
||||
int h;
|
||||
} Character;
|
||||
|
||||
// SpriteFont type, includes texture and charSet array data
|
||||
/*
|
||||
struct SpriteFont {
|
||||
Texture2D texture;
|
||||
int numChars;
|
||||
Character *charSet;
|
||||
};
|
||||
*/
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Global variables
|
||||
|
@ -63,6 +73,11 @@ struct Character {
|
|||
static SpriteFont defaultFont; // Default font provided by raylib
|
||||
// NOTE: defaultFont is loaded on InitWindow and disposed on CloseWindow [module: core]
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Other Modules Functions Declaration (required by text)
|
||||
//----------------------------------------------------------------------------------
|
||||
//...
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module specific Functions Declaration
|
||||
//----------------------------------------------------------------------------------
|
||||
|
@ -78,9 +93,11 @@ static const char *GetExtension(const char *fileName);
|
|||
extern void LoadDefaultFont()
|
||||
{
|
||||
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)
|
||||
// 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
|
||||
|
@ -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,
|
||||
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
|
||||
//------------------------------------------------------------------------------
|
||||
defaultFont.charSet = (Character *)malloc(defaultFont.numChars * sizeof(Character)); // Allocate space for our character data
|
||||
|
@ -146,52 +187,12 @@ extern void LoadDefaultFont()
|
|||
else currentPosX = testPosX;
|
||||
}
|
||||
|
||||
// Re-construct image from defaultFontData and generate OpenGL texture
|
||||
//----------------------------------------------------------------------
|
||||
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;
|
||||
TraceLog(INFO, "Default font loaded successfully");
|
||||
}
|
||||
|
||||
extern void UnloadDefaultFont()
|
||||
{
|
||||
glDeleteTextures(1, &defaultFont.texture.glId);
|
||||
rlDeleteTextures(defaultFont.texture.glId);
|
||||
free(defaultFont.charSet);
|
||||
}
|
||||
|
||||
|
@ -206,6 +207,8 @@ SpriteFont LoadSpriteFont(const char* fileName)
|
|||
{
|
||||
SpriteFont spriteFont;
|
||||
|
||||
Image image;
|
||||
|
||||
// Check file extension
|
||||
if (strcmp(GetExtension(fileName),"rbmf") == 0) spriteFont = LoadRBMF(fileName);
|
||||
else
|
||||
|
@ -240,8 +243,8 @@ SpriteFont LoadSpriteFont(const char* fileName)
|
|||
// spriteFont.charSet data is filled inside the function and memory is allocated!
|
||||
int numChars = ParseImageData(imgDataPixel, imgWidth, imgHeight, &spriteFont.charSet);
|
||||
|
||||
fprintf(stderr, "SpriteFont data parsed correctly!\n");
|
||||
fprintf(stderr, "SpriteFont num chars: %i\n", numChars);
|
||||
TraceLog(INFO, "[%s] SpriteFont data parsed correctly", fileName);
|
||||
TraceLog(INFO, "[%s] SpriteFont num chars detected: %i", 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);
|
||||
|
||||
// Convert loaded data to OpenGL texture
|
||||
//----------------------------------------
|
||||
GLuint id;
|
||||
glGenTextures(1, &id); // Generate pointer to the texture
|
||||
image.pixels = imgDataPixelPOT;
|
||||
image.width = potWidth;
|
||||
image.height = potHeight;
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, id);
|
||||
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, 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;
|
||||
spriteFont.texture = CreateTexture(image); // Convert loaded image to OpenGL texture
|
||||
|
||||
UnloadImage(image);
|
||||
}
|
||||
|
||||
return spriteFont;
|
||||
|
@ -296,7 +288,7 @@ SpriteFont LoadSpriteFont(const char* fileName)
|
|||
// Unload SpriteFont from GPU memory
|
||||
void UnloadSpriteFont(SpriteFont spriteFont)
|
||||
{
|
||||
glDeleteTextures(1, &spriteFont.texture.glId);
|
||||
rlDeleteTextures(spriteFont.texture.glId);
|
||||
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;
|
||||
else scaleFactor = (float)fontSize / spriteFont.charSet[0].h;
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
rlEnableTexture(spriteFont.texture.glId);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, spriteFont.texture.glId);
|
||||
|
||||
// Optimized to use one draw call per string
|
||||
glBegin(GL_QUADS);
|
||||
rlBegin(RL_QUADS);
|
||||
for(int i = 0; i < length; i++)
|
||||
{
|
||||
c = spriteFont.charSet[(int)text[i] - FONT_FIRST_CHAR];
|
||||
|
||||
glColor4ub(tint.r, tint.g, tint.b, tint.a);
|
||||
glNormal3f(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);
|
||||
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);
|
||||
glTexCoord2f((float)(c.x + c.w) / spriteFont.texture.width, (float)c.y / spriteFont.texture.height); glVertex2f(positionX + (c.w) * scaleFactor, position.y);
|
||||
rlColor4ub(tint.r, tint.g, tint.b, tint.a);
|
||||
rlNormal3f(0.0f, 0.0f, 1.0f); // Normal Pointing Towards Viewer
|
||||
|
||||
rlTexCoord2f((float)c.x / spriteFont.texture.width, (float)c.y / spriteFont.texture.height);
|
||||
rlVertex2f(positionX, 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);
|
||||
}
|
||||
glEnd();
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
rlEnd();
|
||||
|
||||
rlDisableTexture();
|
||||
}
|
||||
|
||||
// Formatting of text with variables to 'embed'
|
||||
|
@ -361,7 +358,7 @@ const char *FormatText(const char *text, ...)
|
|||
|
||||
va_list args;
|
||||
va_start(args, text);
|
||||
vsprintf(buffer, text, args); // NOTE: We use vsprintf() defined in <stdarg.h>
|
||||
vsprintf(buffer, text, args);
|
||||
va_end(args);
|
||||
|
||||
return buffer;
|
||||
|
@ -417,21 +414,18 @@ void DrawFPS(int posX, int posY)
|
|||
char buffer[20];
|
||||
|
||||
if (counter < refreshRate)
|
||||
{
|
||||
sprintf(buffer, "%2.0f FPS", fps);
|
||||
DrawText(buffer, posX, posY, 20, LIME);
|
||||
|
||||
{
|
||||
counter++;
|
||||
}
|
||||
else
|
||||
{
|
||||
fps = GetFPS();
|
||||
refreshRate = fps;
|
||||
sprintf(buffer, "%2.0f FPS", fps);
|
||||
DrawText(buffer, posX, posY, 20, LIME);
|
||||
|
||||
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);
|
||||
|
||||
//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;
|
||||
|
||||
|
@ -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);
|
||||
|
||||
printf("Just read image data and width data... Starting image reconstruction...");
|
||||
|
||||
// Re-construct image from rbmfFileData
|
||||
//-----------------------------------------
|
||||
image.pixels = (Color *)malloc(image.width * image.height * sizeof(Color));
|
||||
|
@ -602,13 +594,13 @@ static SpriteFont LoadRBMF(const char *fileName)
|
|||
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);
|
||||
|
||||
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
|
||||
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);
|
||||
}
|
||||
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);
|
||||
|
||||
|
@ -651,6 +641,7 @@ static SpriteFont LoadRBMF(const char *fileName)
|
|||
return spriteFont;
|
||||
}
|
||||
|
||||
// Get the extension for a filename
|
||||
static const char *GetExtension(const char *fileName)
|
||||
{
|
||||
const char *dot = strrchr(fileName, '.');
|
||||
|
|
605
src/textures.c
605
src/textures.c
|
@ -28,12 +28,13 @@
|
|||
|
||||
#include "raylib.h"
|
||||
|
||||
#include <GL/gl.h> // OpenGL functions
|
||||
#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 "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
|
||||
//----------------------------------------------------------------------------------
|
||||
|
@ -44,15 +45,29 @@
|
|||
//----------------------------------------------------------------------------------
|
||||
typedef unsigned char byte;
|
||||
|
||||
typedef struct {
|
||||
unsigned char *data;
|
||||
int width;
|
||||
int height;
|
||||
int mipmaps;
|
||||
int format;
|
||||
} ImageDDS;
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Global Variables Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
// It's lonely here...
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Other Modules Functions Declaration (required by text)
|
||||
//----------------------------------------------------------------------------------
|
||||
//...
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// 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
|
||||
|
@ -63,32 +78,44 @@ Image LoadImage(const char *fileName)
|
|||
{
|
||||
Image image;
|
||||
|
||||
int imgWidth;
|
||||
int imgHeight;
|
||||
int imgBpp;
|
||||
|
||||
// NOTE: Using stb_image to load images (Supports: BMP, TGA, PNG, JPG, ...)
|
||||
// Force loading to 4 components (RGBA)
|
||||
byte *imgData = stbi_load(fileName, &imgWidth, &imgHeight, &imgBpp, 4);
|
||||
|
||||
// Convert array to pixel array for working convenience
|
||||
image.pixels = (Color *)malloc(imgWidth * imgHeight * sizeof(Color));
|
||||
|
||||
int pix = 0;
|
||||
|
||||
for (int i = 0; i < (imgWidth * imgHeight * 4); i += 4)
|
||||
{
|
||||
image.pixels[pix].r = imgData[i];
|
||||
image.pixels[pix].g = imgData[i+1];
|
||||
image.pixels[pix].b = imgData[i+2];
|
||||
image.pixels[pix].a = imgData[i+3];
|
||||
pix++;
|
||||
if ((strcmp(GetExtension(fileName),"png") == 0) ||
|
||||
(strcmp(GetExtension(fileName),"bmp") == 0) ||
|
||||
(strcmp(GetExtension(fileName),"tga") == 0) ||
|
||||
(strcmp(GetExtension(fileName),"jpg") == 0) ||
|
||||
(strcmp(GetExtension(fileName),"gif") == 0) ||
|
||||
(strcmp(GetExtension(fileName),"psd") == 0) ||
|
||||
(strcmp(GetExtension(fileName),"pic") == 0))
|
||||
{
|
||||
int imgWidth;
|
||||
int imgHeight;
|
||||
int imgBpp;
|
||||
|
||||
// NOTE: Using stb_image to load images (Supports: BMP, TGA, PNG, JPG, ...)
|
||||
// Force loading to 4 components (RGBA)
|
||||
byte *imgData = stbi_load(fileName, &imgWidth, &imgHeight, &imgBpp, 4);
|
||||
|
||||
// Convert array to pixel array for working convenience
|
||||
image.pixels = (Color *)malloc(imgWidth * imgHeight * sizeof(Color));
|
||||
|
||||
int pix = 0;
|
||||
|
||||
for (int i = 0; i < (imgWidth * imgHeight * 4); i += 4)
|
||||
{
|
||||
image.pixels[pix].r = imgData[i];
|
||||
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);
|
||||
}
|
||||
|
||||
stbi_image_free(imgData);
|
||||
|
||||
image.width = imgWidth;
|
||||
image.height = imgHeight;
|
||||
else TraceLog(WARNING, "[%s] Image extension not recognized, it can't be loaded", fileName);
|
||||
|
||||
// ALTERNATIVE: We can load pixel data directly into Color struct pixels array,
|
||||
// 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");
|
||||
|
||||
if (!rresFile) printf("Error opening raylib Resource file\n");
|
||||
|
||||
// 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'))
|
||||
if (!rresFile) TraceLog(WARNING, "[%s] Could not open raylib resource file", rresName);
|
||||
else
|
||||
{
|
||||
printf("This is not a valid raylib Resource file!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Read number of resources embedded
|
||||
fread(&numRes, sizeof(short), 1, rresFile);
|
||||
|
||||
for (int i = 0; i < numRes; i++)
|
||||
{
|
||||
fread(&infoHeader, sizeof(ResInfoHeader), 1, rresFile);
|
||||
// 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 (infoHeader.id == resId)
|
||||
if ((id[0] != 'r') && (id[1] != 'R') && (id[2] != 'E') &&(id[3] != 'S'))
|
||||
{
|
||||
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)
|
||||
|
||||
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);
|
||||
}
|
||||
TraceLog(WARNING, "[%s] This is not a valid raylib resource file", 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;
|
||||
}
|
||||
// Read number of resources embedded
|
||||
fread(&numRes, sizeof(short), 1, rresFile);
|
||||
|
||||
// Jump DATA to read next infoHeader
|
||||
fseek(rresFile, infoHeader.size, SEEK_CUR);
|
||||
}
|
||||
for (int i = 0; i < numRes; i++)
|
||||
{
|
||||
fread(&infoHeader, sizeof(ResInfoHeader), 1, rresFile);
|
||||
|
||||
if (infoHeader.id == resId)
|
||||
{
|
||||
found = true;
|
||||
|
||||
// Check data is of valid IMAGE type
|
||||
if (infoHeader.type == 0) // IMAGE data type
|
||||
{
|
||||
// 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) printf("Required resource id could not be found in the raylib Resource file!\n");
|
||||
if (!found) TraceLog(WARNING, "[%s] Required resource id [%i] could not be found in the raylib resource file", rresName, resId);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
@ -218,11 +246,33 @@ Image LoadImageFromRES(const char *rresName, int resId)
|
|||
Texture2D LoadTexture(const char *fileName)
|
||||
{
|
||||
Texture2D texture;
|
||||
Image image;
|
||||
|
||||
image = LoadImage(fileName);
|
||||
texture = CreateTexture(image);
|
||||
UnloadImage(image);
|
||||
|
||||
if (strcmp(GetExtension(fileName),"dds") == 0)
|
||||
{
|
||||
#ifdef USE_OPENGL_11
|
||||
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;
|
||||
}
|
||||
|
@ -238,43 +288,6 @@ Texture2D LoadTextureFromRES(const char *rresName, int resId)
|
|||
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)
|
||||
void UnloadImage(Image image)
|
||||
{
|
||||
|
@ -284,13 +297,13 @@ void UnloadImage(Image image)
|
|||
// Unload texture from GPU memory
|
||||
void UnloadTexture(Texture2D texture)
|
||||
{
|
||||
glDeleteTextures(1, &texture.glId);
|
||||
rlDeleteTextures(texture.glId);
|
||||
}
|
||||
|
||||
// Draw a Texture2D
|
||||
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
|
||||
|
@ -302,101 +315,233 @@ void DrawTextureV(Texture2D texture, Vector2 position, Color tint)
|
|||
// Draw a Texture2D with extended parameters
|
||||
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();
|
||||
// NOTE: Rotation is applied before translation and scaling, even being called in inverse order...
|
||||
// NOTE: Rotation point is upper-left corner
|
||||
glTranslatef(position.x, position.y, 0);
|
||||
glScalef(scale, scale, 1.0f);
|
||||
glRotatef(rotation, 0, 0, 1);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glColor4ub(tint.r, tint.g, tint.b, tint.a);
|
||||
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
|
||||
glTexCoord2f(1.0f, 0.0f); glVertex2f(texture.width, 0.0f); // Bottom-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
|
||||
glEnd();
|
||||
glPopMatrix();
|
||||
rlBegin(RL_QUADS);
|
||||
rlColor4ub(tint.r, tint.g, tint.b, tint.a);
|
||||
rlNormal3f(0.0f, 0.0f, 1.0f); // Normal vector pointing towards viewer
|
||||
|
||||
rlTexCoord2f(0.0f, 0.0f);
|
||||
rlVertex2f(position.x, position.y); // Bottom-left corner for texture and quad
|
||||
|
||||
rlTexCoord2f(0.0f, 1.0f);
|
||||
rlVertex2f(position.x, position.y + texture.height); // Bottom-right corner for texture and quad
|
||||
|
||||
rlTexCoord2f(1.0f, 1.0f);
|
||||
rlVertex2f(position.x + texture.width, position.y + texture.height); // Top-right corner for texture and quad
|
||||
|
||||
rlTexCoord2f(1.0f, 0.0f);
|
||||
rlVertex2f(position.x + texture.width, position.y); // Top-left corner for texture and quad
|
||||
rlEnd();
|
||||
rlPopMatrix();
|
||||
|
||||
glDisable(GL_TEXTURE_2D); // Disable textures usage
|
||||
rlDisableTexture();
|
||||
}
|
||||
|
||||
// Draw a part of a texture (defined by a rectangle)
|
||||
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);
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(position.x, position.y, 0);
|
||||
//glScalef(1.0f, 1.0f, 1.0f);
|
||||
//glRotatef(rotation, 0, 0, 1);
|
||||
rlBegin(RL_QUADS);
|
||||
rlColor4ub(tint.r, tint.g, tint.b, tint.a);
|
||||
rlNormal3f(0.0f, 0.0f, 1.0f); // Normal vector pointing towards viewer
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glColor4ub(tint.r, tint.g, tint.b, tint.a);
|
||||
glNormal3f(0.0f, 0.0f, 1.0f); // Normal vector pointing towards viewer
|
||||
|
||||
// Bottom-left corner for texture and quad
|
||||
glTexCoord2f((float)sourceRec.x / texture.width, (float)sourceRec.y / texture.height);
|
||||
glVertex2f(0.0f, 0.0f);
|
||||
|
||||
// Bottom-right corner for texture and quad
|
||||
glTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)sourceRec.y / texture.height);
|
||||
glVertex2f(sourceRec.width, 0.0f);
|
||||
|
||||
// Top-right corner for texture and quad
|
||||
glTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height);
|
||||
glVertex2f(sourceRec.width, sourceRec.height);
|
||||
|
||||
// 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();
|
||||
// Bottom-left corner for texture and quad
|
||||
rlTexCoord2f((float)sourceRec.x / texture.width, (float)sourceRec.y / texture.height);
|
||||
rlVertex2f(position.x, position.y);
|
||||
|
||||
// Bottom-right corner for texture and quad
|
||||
rlTexCoord2f((float)sourceRec.x / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height);
|
||||
rlVertex2f(position.x, position.y + sourceRec.height);
|
||||
|
||||
// Top-right corner for texture and quad
|
||||
rlTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height);
|
||||
rlVertex2f(position.x + sourceRec.width, position.y + sourceRec.height);
|
||||
|
||||
// Top-left corner for texture and quad
|
||||
rlTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)sourceRec.y / texture.height);
|
||||
rlVertex2f(position.x + sourceRec.width, position.y);
|
||||
rlEnd();
|
||||
|
||||
glDisable(GL_TEXTURE_2D); // Disable textures usage
|
||||
rlDisableTexture();
|
||||
}
|
||||
|
||||
// Draw a part of a texture (defined by a rectangle) with 'pro' parameters
|
||||
// TODO: Test this function...
|
||||
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);
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(-origin.x, -origin.y, 0);
|
||||
glRotatef(rotation, 0, 0, 1);
|
||||
glTranslatef(destRec.x + origin.x, destRec.y + origin.y, 0);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glColor4ub(tint.r, tint.g, tint.b, tint.a);
|
||||
glNormal3f(0.0f, 0.0f, 1.0f); // Normal vector pointing towards viewer
|
||||
// NOTE: First we translate texture to origin to apply rotation and translation from there
|
||||
rlPushMatrix();
|
||||
rlTranslatef(-origin.x, -origin.y, 0);
|
||||
rlRotatef(rotation, 0, 0, 1);
|
||||
rlTranslatef(destRec.x + origin.x, destRec.y + origin.y, 0);
|
||||
|
||||
rlBegin(RL_QUADS);
|
||||
rlColor4ub(tint.r, tint.g, tint.b, tint.a);
|
||||
rlNormal3f(0.0f, 0.0f, 1.0f); // Normal vector pointing towards viewer
|
||||
|
||||
// Bottom-left corner for texture and quad
|
||||
glTexCoord2f((float)sourceRec.x / texture.width, (float)sourceRec.y / texture.height);
|
||||
glVertex2f(0.0f, 0.0f);
|
||||
rlTexCoord2f((float)sourceRec.x / texture.width, (float)sourceRec.y / texture.height);
|
||||
rlVertex2f(0.0f, 0.0f);
|
||||
|
||||
// Bottom-right corner for texture and quad
|
||||
glTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)sourceRec.y / texture.height);
|
||||
glVertex2f(destRec.width, 0.0f);
|
||||
rlTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)sourceRec.y / texture.height);
|
||||
rlVertex2f(destRec.width, 0.0f);
|
||||
|
||||
// Top-right corner for texture and quad
|
||||
glTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height);
|
||||
glVertex2f(destRec.width, destRec.height);
|
||||
rlTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height);
|
||||
rlVertex2f(destRec.width, destRec.height);
|
||||
|
||||
// Top-left corner for texture and quad
|
||||
glTexCoord2f((float)sourceRec.x / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height);
|
||||
glVertex2f(0.0f, destRec.height);
|
||||
glEnd();
|
||||
glPopMatrix();
|
||||
rlTexCoord2f((float)sourceRec.x / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height);
|
||||
rlVertex2f(0.0f, destRec.height);
|
||||
rlEnd();
|
||||
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 <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()
|
||||
|
||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
|
@ -37,6 +38,15 @@
|
|||
#include "stb_image_write.h" // Create PNG file
|
||||
#include "tinfl.c"
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Global Variables Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
static FILE *logstream = NULL;
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module Functions Definition - Utilities
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Data decompression function
|
||||
// NOTE: Allocated data MUST be freed!
|
||||
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
|
||||
if (!pUncomp)
|
||||
{
|
||||
printf("Out of memory!\n");
|
||||
return NULL;
|
||||
TraceLog(WARNING, "Out of memory while decompressing data");
|
||||
}
|
||||
|
||||
// Decompress data
|
||||
tempUncompSize = tinfl_decompress_mem_to_mem(pUncomp, (size_t)uncompSize, data, compSize, 1);
|
||||
|
||||
if (tempUncompSize == -1)
|
||||
else
|
||||
{
|
||||
printf("Decompression failed!\n");
|
||||
free(pUncomp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (uncompSize != (int)tempUncompSize)
|
||||
{
|
||||
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);
|
||||
}
|
||||
// Decompress data
|
||||
tempUncompSize = tinfl_decompress_mem_to_mem(pUncomp, (size_t)uncompSize, data, compSize, 1);
|
||||
|
||||
if (tempUncompSize == -1)
|
||||
{
|
||||
TraceLog(WARNING, "Data decompression failed");
|
||||
free(pUncomp);
|
||||
}
|
||||
|
||||
if (uncompSize != (int)tempUncompSize)
|
||||
{
|
||||
TraceLog(WARNING, "Expected uncompressed size do not match, data may be corrupted");
|
||||
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;
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
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
|
||||
//----------------------------------------------------------------------------------
|
||||
//...
|
||||
//#define DO_NOT_TRACE_DEBUG_MSGS // Use this define to avoid DEBUG tracing
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Types and Structures Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
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)
|
||||
typedef struct {
|
||||
unsigned short id; // Resource unique identifier (2 byte)
|
||||
|
@ -61,9 +63,14 @@ extern "C" { // Prevents name mangling of functions
|
|||
// Module Functions Declaration
|
||||
//----------------------------------------------------------------------------------
|
||||
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 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
|
||||
}
|
||||
#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