Update C sources, add new functions
This commit is contained in:
parent
661c7a9f55
commit
0f4ce7d6d9
30 changed files with 8465 additions and 2315 deletions
197
raylib/audio.c
197
raylib/audio.c
|
@ -69,6 +69,7 @@
|
|||
#define SUPPORT_FILEFORMAT_WAV
|
||||
#define SUPPORT_FILEFORMAT_OGG
|
||||
#define SUPPORT_FILEFORMAT_XM
|
||||
#define SUPPORT_FILEFORMAT_MOD
|
||||
//-------------------------------------------------
|
||||
|
||||
#if defined(AUDIO_STANDALONE)
|
||||
|
@ -79,7 +80,7 @@
|
|||
#include "utils.h" // Required for: fopen() Android mapping
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
#if defined(__APPLE__)
|
||||
#include "OpenAL/al.h" // OpenAL basic header
|
||||
#include "OpenAL/alc.h" // OpenAL context header (like OpenGL, OpenAL requires a context to work)
|
||||
#else
|
||||
|
@ -170,7 +171,7 @@ typedef struct MusicData {
|
|||
} MusicData;
|
||||
|
||||
#if defined(AUDIO_STANDALONE)
|
||||
typedef enum { INFO = 0, ERROR, WARNING, DEBUG, OTHER } TraceLogType;
|
||||
typedef enum { LOG_INFO = 0, LOG_ERROR, LOG_WARNING, LOG_DEBUG, LOG_OTHER } TraceLogType;
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
|
@ -193,7 +194,7 @@ static Wave LoadFLAC(const char *fileName); // Load FLAC file
|
|||
|
||||
#if defined(AUDIO_STANDALONE)
|
||||
bool IsFileExtension(const char *fileName, const char *ext); // Check file extension
|
||||
void TraceLog(int msgType, const char *text, ...); // Outputs trace log message (INFO, ERROR, WARNING)
|
||||
void TraceLog(int msgType, const char *text, ...); // Show trace log messages (LOG_INFO, LOG_WARNING, LOG_ERROR, LOG_DEBUG)
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
|
@ -206,7 +207,7 @@ void InitAudioDevice(void)
|
|||
// Open and initialize a device with default settings
|
||||
ALCdevice *device = alcOpenDevice(NULL);
|
||||
|
||||
if (!device) TraceLog(ERROR, "Audio device could not be opened");
|
||||
if (!device) TraceLog(LOG_ERROR, "Audio device could not be opened");
|
||||
else
|
||||
{
|
||||
ALCcontext *context = alcCreateContext(device, NULL);
|
||||
|
@ -217,11 +218,11 @@ void InitAudioDevice(void)
|
|||
|
||||
alcCloseDevice(device);
|
||||
|
||||
TraceLog(ERROR, "Could not initialize audio context");
|
||||
TraceLog(LOG_ERROR, "Could not initialize audio context");
|
||||
}
|
||||
else
|
||||
{
|
||||
TraceLog(INFO, "Audio device and context initialized successfully: %s", alcGetString(device, ALC_DEVICE_SPECIFIER));
|
||||
TraceLog(LOG_INFO, "Audio device and context initialized successfully: %s", alcGetString(device, ALC_DEVICE_SPECIFIER));
|
||||
|
||||
// Listener definition (just for 2D)
|
||||
alListener3f(AL_POSITION, 0.0f, 0.0f, 0.0f);
|
||||
|
@ -239,7 +240,7 @@ void CloseAudioDevice(void)
|
|||
ALCdevice *device;
|
||||
ALCcontext *context = alcGetCurrentContext();
|
||||
|
||||
if (context == NULL) TraceLog(WARNING, "Could not get current audio context for closing");
|
||||
if (context == NULL) TraceLog(LOG_WARNING, "Could not get current audio context for closing");
|
||||
|
||||
device = alcGetContextsDevice(context);
|
||||
|
||||
|
@ -247,7 +248,7 @@ void CloseAudioDevice(void)
|
|||
alcDestroyContext(context);
|
||||
alcCloseDevice(device);
|
||||
|
||||
TraceLog(INFO, "Audio device closed successfully");
|
||||
TraceLog(LOG_INFO, "Audio device closed successfully");
|
||||
}
|
||||
|
||||
// Check if device has been initialized successfully
|
||||
|
@ -298,12 +299,12 @@ Wave LoadWave(const char *fileName)
|
|||
// NOTE: Parameters for RRES_TYPE_WAVE are: sampleCount, sampleRate, sampleSize, channels
|
||||
|
||||
if (rres[0].type == RRES_TYPE_WAVE) wave = LoadWaveEx(rres[0].data, rres[0].param1, rres[0].param2, rres[0].param3, rres[0].param4);
|
||||
else TraceLog(WARNING, "[%s] Resource file does not contain wave data", fileName);
|
||||
else TraceLog(LOG_WARNING, "[%s] Resource file does not contain wave data", fileName);
|
||||
|
||||
UnloadResource(rres);
|
||||
}
|
||||
#endif
|
||||
else TraceLog(WARNING, "[%s] Audio fileformat not supported, it can't be loaded", fileName);
|
||||
else TraceLog(LOG_WARNING, "[%s] Audio fileformat not supported, it can't be loaded", fileName);
|
||||
|
||||
return wave;
|
||||
}
|
||||
|
@ -358,7 +359,7 @@ Sound LoadSoundFromWave(Wave wave)
|
|||
case 8: format = AL_FORMAT_MONO8; break;
|
||||
case 16: format = AL_FORMAT_MONO16; break;
|
||||
case 32: format = AL_FORMAT_MONO_FLOAT32; break; // Requires OpenAL extension: AL_EXT_FLOAT32
|
||||
default: TraceLog(WARNING, "Wave sample size not supported: %i", wave.sampleSize); break;
|
||||
default: TraceLog(LOG_WARNING, "Wave sample size not supported: %i", wave.sampleSize); break;
|
||||
}
|
||||
}
|
||||
else if (wave.channels == 2)
|
||||
|
@ -368,10 +369,10 @@ Sound LoadSoundFromWave(Wave wave)
|
|||
case 8: format = AL_FORMAT_STEREO8; break;
|
||||
case 16: format = AL_FORMAT_STEREO16; break;
|
||||
case 32: format = AL_FORMAT_STEREO_FLOAT32; break; // Requires OpenAL extension: AL_EXT_FLOAT32
|
||||
default: TraceLog(WARNING, "Wave sample size not supported: %i", wave.sampleSize); break;
|
||||
default: TraceLog(LOG_WARNING, "Wave sample size not supported: %i", wave.sampleSize); break;
|
||||
}
|
||||
}
|
||||
else TraceLog(WARNING, "Wave number of channels not supported: %i", wave.channels);
|
||||
else TraceLog(LOG_WARNING, "Wave number of channels not supported: %i", wave.channels);
|
||||
|
||||
// Create an audio source
|
||||
ALuint source;
|
||||
|
@ -396,7 +397,7 @@ Sound LoadSoundFromWave(Wave wave)
|
|||
// Attach sound buffer to source
|
||||
alSourcei(source, AL_BUFFER, buffer);
|
||||
|
||||
TraceLog(INFO, "[SND ID %i][BUFR ID %i] Sound data loaded successfully (%i Hz, %i bit, %s)", source, buffer, wave.sampleRate, wave.sampleSize, (wave.channels == 1) ? "Mono" : "Stereo");
|
||||
TraceLog(LOG_INFO, "[SND ID %i][BUFR ID %i] Sound data loaded successfully (%i Hz, %i bit, %s)", source, buffer, wave.sampleRate, wave.sampleSize, (wave.channels == 1) ? "Mono" : "Stereo");
|
||||
|
||||
sound.source = source;
|
||||
sound.buffer = buffer;
|
||||
|
@ -411,7 +412,7 @@ void UnloadWave(Wave wave)
|
|||
{
|
||||
if (wave.data != NULL) free(wave.data);
|
||||
|
||||
TraceLog(INFO, "Unloaded wave data from RAM");
|
||||
TraceLog(LOG_INFO, "Unloaded wave data from RAM");
|
||||
}
|
||||
|
||||
// Unload sound
|
||||
|
@ -422,7 +423,7 @@ void UnloadSound(Sound sound)
|
|||
alDeleteSources(1, &sound.source);
|
||||
alDeleteBuffers(1, &sound.buffer);
|
||||
|
||||
TraceLog(INFO, "[SND ID %i][BUFR ID %i] Unloaded sound data from RAM", sound.source, sound.buffer);
|
||||
TraceLog(LOG_INFO, "[SND ID %i][BUFR ID %i] Unloaded sound data from RAM", sound.source, sound.buffer);
|
||||
}
|
||||
|
||||
// Update sound buffer with new data
|
||||
|
@ -434,9 +435,9 @@ void UpdateSound(Sound sound, const void *data, int samplesCount)
|
|||
alGetBufferi(sound.buffer, AL_BITS, &sampleSize); // It could also be retrieved from sound.format
|
||||
alGetBufferi(sound.buffer, AL_CHANNELS, &channels); // It could also be retrieved from sound.format
|
||||
|
||||
TraceLog(DEBUG, "UpdateSound() : AL_FREQUENCY: %i", sampleRate);
|
||||
TraceLog(DEBUG, "UpdateSound() : AL_BITS: %i", sampleSize);
|
||||
TraceLog(DEBUG, "UpdateSound() : AL_CHANNELS: %i", channels);
|
||||
TraceLog(LOG_DEBUG, "UpdateSound() : AL_FREQUENCY: %i", sampleRate);
|
||||
TraceLog(LOG_DEBUG, "UpdateSound() : AL_BITS: %i", sampleSize);
|
||||
TraceLog(LOG_DEBUG, "UpdateSound() : AL_CHANNELS: %i", channels);
|
||||
|
||||
unsigned int dataSize = samplesCount*channels*sampleSize/8; // Size of data in bytes
|
||||
|
||||
|
@ -457,7 +458,7 @@ void PlaySound(Sound sound)
|
|||
{
|
||||
alSourcePlay(sound.source); // Play the sound
|
||||
|
||||
//TraceLog(INFO, "Playing sound");
|
||||
//TraceLog(LOG_INFO, "Playing sound");
|
||||
|
||||
// Find the current position of the sound being played
|
||||
// NOTE: Only work when the entire file is in a single buffer
|
||||
|
@ -570,7 +571,7 @@ void WaveFormat(Wave *wave, int sampleRate, int sampleSize, int channels)
|
|||
// NOTE: Only supported mono <--> stereo
|
||||
if (wave->channels != channels)
|
||||
{
|
||||
void *data = malloc(wave->sampleCount*channels*wave->sampleSize/8);
|
||||
void *data = malloc(wave->sampleCount*wave->sampleSize/8*channels);
|
||||
|
||||
if ((wave->channels == 1) && (channels == 2)) // mono ---> stereo (duplicate mono information)
|
||||
{
|
||||
|
@ -607,7 +608,7 @@ Wave WaveCopy(Wave wave)
|
|||
{
|
||||
Wave newWave = { 0 };
|
||||
|
||||
newWave.data = malloc(wave.sampleCount*wave.channels*wave.sampleSize/8);
|
||||
newWave.data = malloc(wave.sampleCount*wave.sampleSize/8*wave.channels);
|
||||
|
||||
if (newWave.data != NULL)
|
||||
{
|
||||
|
@ -632,14 +633,14 @@ void WaveCrop(Wave *wave, int initSample, int finalSample)
|
|||
{
|
||||
int sampleCount = finalSample - initSample;
|
||||
|
||||
void *data = malloc(sampleCount*wave->channels*wave->sampleSize/8);
|
||||
void *data = malloc(sampleCount*wave->sampleSize/8*wave->channels);
|
||||
|
||||
memcpy(data, (unsigned char*)wave->data + (initSample*wave->channels*wave->sampleSize/8), sampleCount*wave->channels*wave->sampleSize/8);
|
||||
|
||||
free(wave->data);
|
||||
wave->data = data;
|
||||
}
|
||||
else TraceLog(WARNING, "Wave crop range out of bounds");
|
||||
else TraceLog(LOG_WARNING, "Wave crop range out of bounds");
|
||||
}
|
||||
|
||||
// Get samples data from wave as a floats array
|
||||
|
@ -675,7 +676,7 @@ Music LoadMusicStream(const char *fileName)
|
|||
// Open ogg audio stream
|
||||
music->ctxOgg = stb_vorbis_open_filename(fileName, NULL, NULL);
|
||||
|
||||
if (music->ctxOgg == NULL) TraceLog(WARNING, "[%s] OGG audio file could not be opened", fileName);
|
||||
if (music->ctxOgg == NULL) TraceLog(LOG_WARNING, "[%s] OGG audio file could not be opened", fileName);
|
||||
else
|
||||
{
|
||||
stb_vorbis_info info = stb_vorbis_get_info(music->ctxOgg); // Get Ogg file info
|
||||
|
@ -687,10 +688,10 @@ Music LoadMusicStream(const char *fileName)
|
|||
music->ctxType = MUSIC_AUDIO_OGG;
|
||||
music->loopCount = -1; // Infinite loop by default
|
||||
|
||||
TraceLog(DEBUG, "[%s] FLAC total samples: %i", fileName, music->totalSamples);
|
||||
TraceLog(DEBUG, "[%s] OGG sample rate: %i", fileName, info.sample_rate);
|
||||
TraceLog(DEBUG, "[%s] OGG channels: %i", fileName, info.channels);
|
||||
TraceLog(DEBUG, "[%s] OGG memory required: %i", fileName, info.temp_memory_required);
|
||||
TraceLog(LOG_DEBUG, "[%s] FLAC total samples: %i", fileName, music->totalSamples);
|
||||
TraceLog(LOG_DEBUG, "[%s] OGG sample rate: %i", fileName, info.sample_rate);
|
||||
TraceLog(LOG_DEBUG, "[%s] OGG channels: %i", fileName, info.channels);
|
||||
TraceLog(LOG_DEBUG, "[%s] OGG memory required: %i", fileName, info.temp_memory_required);
|
||||
}
|
||||
}
|
||||
#if defined(SUPPORT_FILEFORMAT_FLAC)
|
||||
|
@ -698,7 +699,7 @@ Music LoadMusicStream(const char *fileName)
|
|||
{
|
||||
music->ctxFlac = drflac_open_file(fileName);
|
||||
|
||||
if (music->ctxFlac == NULL) TraceLog(WARNING, "[%s] FLAC audio file could not be opened", fileName);
|
||||
if (music->ctxFlac == NULL) TraceLog(LOG_WARNING, "[%s] FLAC audio file could not be opened", fileName);
|
||||
else
|
||||
{
|
||||
music->stream = InitAudioStream(music->ctxFlac->sampleRate, music->ctxFlac->bitsPerSample, music->ctxFlac->channels);
|
||||
|
@ -707,10 +708,10 @@ Music LoadMusicStream(const char *fileName)
|
|||
music->ctxType = MUSIC_AUDIO_FLAC;
|
||||
music->loopCount = -1; // Infinite loop by default
|
||||
|
||||
TraceLog(DEBUG, "[%s] FLAC total samples: %i", fileName, music->totalSamples);
|
||||
TraceLog(DEBUG, "[%s] FLAC sample rate: %i", fileName, music->ctxFlac->sampleRate);
|
||||
TraceLog(DEBUG, "[%s] FLAC bits per sample: %i", fileName, music->ctxFlac->bitsPerSample);
|
||||
TraceLog(DEBUG, "[%s] FLAC channels: %i", fileName, music->ctxFlac->channels);
|
||||
TraceLog(LOG_DEBUG, "[%s] FLAC total samples: %i", fileName, music->totalSamples);
|
||||
TraceLog(LOG_DEBUG, "[%s] FLAC sample rate: %i", fileName, music->ctxFlac->sampleRate);
|
||||
TraceLog(LOG_DEBUG, "[%s] FLAC bits per sample: %i", fileName, music->ctxFlac->bitsPerSample);
|
||||
TraceLog(LOG_DEBUG, "[%s] FLAC channels: %i", fileName, music->ctxFlac->channels);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -730,10 +731,10 @@ Music LoadMusicStream(const char *fileName)
|
|||
music->ctxType = MUSIC_MODULE_XM;
|
||||
music->loopCount = -1; // Infinite loop by default
|
||||
|
||||
TraceLog(DEBUG, "[%s] XM number of samples: %i", fileName, music->totalSamples);
|
||||
TraceLog(DEBUG, "[%s] XM track length: %11.6f sec", fileName, (float)music->totalSamples/48000.0f);
|
||||
TraceLog(LOG_DEBUG, "[%s] XM number of samples: %i", fileName, music->totalSamples);
|
||||
TraceLog(LOG_DEBUG, "[%s] XM track length: %11.6f sec", fileName, (float)music->totalSamples/48000.0f);
|
||||
}
|
||||
else TraceLog(WARNING, "[%s] XM file could not be opened", fileName);
|
||||
else TraceLog(LOG_WARNING, "[%s] XM file could not be opened", fileName);
|
||||
}
|
||||
#endif
|
||||
#if defined(SUPPORT_FILEFORMAT_MOD)
|
||||
|
@ -749,13 +750,13 @@ Music LoadMusicStream(const char *fileName)
|
|||
music->ctxType = MUSIC_MODULE_MOD;
|
||||
music->loopCount = -1; // Infinite loop by default
|
||||
|
||||
TraceLog(DEBUG, "[%s] MOD number of samples: %i", fileName, music->samplesLeft);
|
||||
TraceLog(DEBUG, "[%s] MOD track length: %11.6f sec", fileName, (float)music->totalSamples/48000.0f);
|
||||
TraceLog(LOG_DEBUG, "[%s] MOD number of samples: %i", fileName, music->samplesLeft);
|
||||
TraceLog(LOG_DEBUG, "[%s] MOD track length: %11.6f sec", fileName, (float)music->totalSamples/48000.0f);
|
||||
}
|
||||
else TraceLog(WARNING, "[%s] MOD file could not be opened", fileName);
|
||||
else TraceLog(LOG_WARNING, "[%s] MOD file could not be opened", fileName);
|
||||
}
|
||||
#endif
|
||||
else TraceLog(WARNING, "[%s] Audio fileformat not supported, it can't be loaded", fileName);
|
||||
else TraceLog(LOG_WARNING, "[%s] Audio fileformat not supported, it can't be loaded", fileName);
|
||||
|
||||
return music;
|
||||
}
|
||||
|
@ -797,23 +798,32 @@ void ResumeMusicStream(Music music)
|
|||
ALenum state;
|
||||
alGetSourcei(music->stream.source, AL_SOURCE_STATE, &state);
|
||||
|
||||
if (state == AL_PAUSED) alSourcePlay(music->stream.source);
|
||||
if (state == AL_PAUSED)
|
||||
{
|
||||
TraceLog(LOG_INFO, "[AUD ID %i] Resume music stream playing", music->stream.source);
|
||||
alSourcePlay(music->stream.source);
|
||||
}
|
||||
}
|
||||
|
||||
// Stop music playing (close stream)
|
||||
// TODO: To clear a buffer, make sure they have been already processed!
|
||||
void StopMusicStream(Music music)
|
||||
{
|
||||
alSourceStop(music->stream.source);
|
||||
|
||||
/*
|
||||
// Clear stream buffers
|
||||
// WARNING: Queued buffers must have been processed before unqueueing and reloaded with data!!!
|
||||
void *pcm = calloc(AUDIO_BUFFER_SIZE*music->stream.sampleSize/8*music->stream.channels, 1);
|
||||
|
||||
|
||||
for (int i = 0; i < MAX_STREAM_BUFFERS; i++)
|
||||
{
|
||||
//UpdateAudioStream(music->stream, pcm, AUDIO_BUFFER_SIZE); // Update one buffer at a time
|
||||
alBufferData(music->stream.buffers[i], music->stream.format, pcm, AUDIO_BUFFER_SIZE*music->stream.sampleSize/8*music->stream.channels, music->stream.sampleRate);
|
||||
}
|
||||
|
||||
free(pcm);
|
||||
*/
|
||||
|
||||
// Restart music context
|
||||
switch (music->ctxType)
|
||||
|
@ -846,14 +856,14 @@ void UpdateMusicStream(Music music)
|
|||
|
||||
if (processed > 0)
|
||||
{
|
||||
bool active = true;
|
||||
bool streamEnding = false;
|
||||
|
||||
// NOTE: Using dynamic allocation because it could require more than 16KB
|
||||
void *pcm = calloc(AUDIO_BUFFER_SIZE*music->stream.channels*music->stream.sampleSize/8, 1);
|
||||
void *pcm = calloc(AUDIO_BUFFER_SIZE*music->stream.sampleSize/8*music->stream.channels, 1);
|
||||
|
||||
int numBuffersToProcess = processed;
|
||||
int samplesCount = 0; // Total size of data steamed in L+R samples for xm floats,
|
||||
//individual L or R for ogg shorts
|
||||
// individual L or R for ogg shorts
|
||||
|
||||
for (int i = 0; i < numBuffersToProcess; i++)
|
||||
{
|
||||
|
@ -891,16 +901,16 @@ void UpdateMusicStream(Music music)
|
|||
|
||||
if (music->samplesLeft <= 0)
|
||||
{
|
||||
active = false;
|
||||
streamEnding = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// This error is registered when UpdateAudioStream() fails
|
||||
if (alGetError() == AL_INVALID_VALUE) TraceLog(WARNING, "OpenAL: Error buffering data...");
|
||||
|
||||
// Free allocated pcm data
|
||||
free(pcm);
|
||||
|
||||
// Reset audio stream for looping
|
||||
if (!active)
|
||||
if (streamEnding)
|
||||
{
|
||||
StopMusicStream(music); // Stop music (and reset)
|
||||
|
||||
|
@ -917,8 +927,6 @@ void UpdateMusicStream(Music music)
|
|||
// just make sure to play again on window restore
|
||||
if (state != AL_PLAYING) PlayMusicStream(music);
|
||||
}
|
||||
|
||||
free(pcm);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -985,7 +993,7 @@ AudioStream InitAudioStream(unsigned int sampleRate, unsigned int sampleSize, un
|
|||
if ((channels > 0) && (channels < 3)) stream.channels = channels;
|
||||
else
|
||||
{
|
||||
TraceLog(WARNING, "Init audio stream: Number of channels not supported: %i", channels);
|
||||
TraceLog(LOG_WARNING, "Init audio stream: Number of channels not supported: %i", channels);
|
||||
stream.channels = 1; // Fallback to mono channel
|
||||
}
|
||||
|
||||
|
@ -997,7 +1005,7 @@ AudioStream InitAudioStream(unsigned int sampleRate, unsigned int sampleSize, un
|
|||
case 8: stream.format = AL_FORMAT_MONO8; break;
|
||||
case 16: stream.format = AL_FORMAT_MONO16; break;
|
||||
case 32: stream.format = AL_FORMAT_MONO_FLOAT32; break; // Requires OpenAL extension: AL_EXT_FLOAT32
|
||||
default: TraceLog(WARNING, "Init audio stream: Sample size not supported: %i", sampleSize); break;
|
||||
default: TraceLog(LOG_WARNING, "Init audio stream: Sample size not supported: %i", sampleSize); break;
|
||||
}
|
||||
}
|
||||
else if (stream.channels == 2)
|
||||
|
@ -1007,7 +1015,7 @@ AudioStream InitAudioStream(unsigned int sampleRate, unsigned int sampleSize, un
|
|||
case 8: stream.format = AL_FORMAT_STEREO8; break;
|
||||
case 16: stream.format = AL_FORMAT_STEREO16; break;
|
||||
case 32: stream.format = AL_FORMAT_STEREO_FLOAT32; break; // Requires OpenAL extension: AL_EXT_FLOAT32
|
||||
default: TraceLog(WARNING, "Init audio stream: Sample size not supported: %i", sampleSize); break;
|
||||
default: TraceLog(LOG_WARNING, "Init audio stream: Sample size not supported: %i", sampleSize); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1034,7 +1042,7 @@ AudioStream InitAudioStream(unsigned int sampleRate, unsigned int sampleSize, un
|
|||
|
||||
alSourceQueueBuffers(stream.source, MAX_STREAM_BUFFERS, stream.buffers);
|
||||
|
||||
TraceLog(INFO, "[AUD ID %i] Audio stream loaded successfully (%i Hz, %i bit, %s)", stream.source, stream.sampleRate, stream.sampleSize, (stream.channels == 1) ? "Mono" : "Stereo");
|
||||
TraceLog(LOG_INFO, "[AUD ID %i] Audio stream loaded successfully (%i Hz, %i bit, %s)", stream.source, stream.sampleRate, stream.sampleSize, (stream.channels == 1) ? "Mono" : "Stereo");
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
@ -1061,11 +1069,12 @@ void CloseAudioStream(AudioStream stream)
|
|||
alDeleteSources(1, &stream.source);
|
||||
alDeleteBuffers(MAX_STREAM_BUFFERS, stream.buffers);
|
||||
|
||||
TraceLog(INFO, "[AUD ID %i] Unloaded audio stream data", stream.source);
|
||||
TraceLog(LOG_INFO, "[AUD ID %i] Unloaded audio stream data", stream.source);
|
||||
}
|
||||
|
||||
// Update audio stream buffers with data
|
||||
// NOTE: Only updates one buffer per call
|
||||
// NOTE 1: Only updates one buffer of the stream source: unqueue -> update -> queue
|
||||
// NOTE 2: To unqueue a buffer it needs to be processed: IsAudioBufferProcessed()
|
||||
void UpdateAudioStream(AudioStream stream, const void *data, int samplesCount)
|
||||
{
|
||||
ALuint buffer = 0;
|
||||
|
@ -1074,9 +1083,10 @@ void UpdateAudioStream(AudioStream stream, const void *data, int samplesCount)
|
|||
// Check if any buffer was available for unqueue
|
||||
if (alGetError() != AL_INVALID_VALUE)
|
||||
{
|
||||
alBufferData(buffer, stream.format, data, samplesCount*stream.channels*stream.sampleSize/8, stream.sampleRate);
|
||||
alBufferData(buffer, stream.format, data, samplesCount*stream.sampleSize/8*stream.channels, stream.sampleRate);
|
||||
alSourceQueueBuffers(stream.source, 1, &buffer);
|
||||
}
|
||||
else TraceLog(LOG_WARNING, "[AUD ID %i] Audio buffer not available for unqueuing", stream.source);
|
||||
}
|
||||
|
||||
// Check if any audio stream buffers requires refill
|
||||
|
@ -1159,7 +1169,7 @@ static Wave LoadWAV(const char *fileName)
|
|||
|
||||
if (wavFile == NULL)
|
||||
{
|
||||
TraceLog(WARNING, "[%s] WAV file could not be opened", fileName);
|
||||
TraceLog(LOG_WARNING, "[%s] WAV file could not be opened", fileName);
|
||||
wave.data = NULL;
|
||||
}
|
||||
else
|
||||
|
@ -1171,7 +1181,7 @@ static Wave LoadWAV(const char *fileName)
|
|||
if (strncmp(wavRiffHeader.chunkID, "RIFF", 4) ||
|
||||
strncmp(wavRiffHeader.format, "WAVE", 4))
|
||||
{
|
||||
TraceLog(WARNING, "[%s] Invalid RIFF or WAVE Header", fileName);
|
||||
TraceLog(LOG_WARNING, "[%s] Invalid RIFF or WAVE Header", fileName);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1182,7 +1192,7 @@ static Wave LoadWAV(const char *fileName)
|
|||
if ((wavFormat.subChunkID[0] != 'f') || (wavFormat.subChunkID[1] != 'm') ||
|
||||
(wavFormat.subChunkID[2] != 't') || (wavFormat.subChunkID[3] != ' '))
|
||||
{
|
||||
TraceLog(WARNING, "[%s] Invalid Wave format", fileName);
|
||||
TraceLog(LOG_WARNING, "[%s] Invalid Wave format", fileName);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1196,7 +1206,7 @@ static Wave LoadWAV(const char *fileName)
|
|||
if ((wavData.subChunkID[0] != 'd') || (wavData.subChunkID[1] != 'a') ||
|
||||
(wavData.subChunkID[2] != 't') || (wavData.subChunkID[3] != 'a'))
|
||||
{
|
||||
TraceLog(WARNING, "[%s] Invalid data header", fileName);
|
||||
TraceLog(LOG_WARNING, "[%s] Invalid data header", fileName);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1214,7 +1224,7 @@ static Wave LoadWAV(const char *fileName)
|
|||
// NOTE: Only support 8 bit, 16 bit and 32 bit sample sizes
|
||||
if ((wave.sampleSize != 8) && (wave.sampleSize != 16) && (wave.sampleSize != 32))
|
||||
{
|
||||
TraceLog(WARNING, "[%s] WAV sample size (%ibit) not supported, converted to 16bit", fileName, wave.sampleSize);
|
||||
TraceLog(LOG_WARNING, "[%s] WAV sample size (%ibit) not supported, converted to 16bit", fileName, wave.sampleSize);
|
||||
WaveFormat(&wave, wave.sampleRate, 16, wave.channels);
|
||||
}
|
||||
|
||||
|
@ -1222,13 +1232,13 @@ static Wave LoadWAV(const char *fileName)
|
|||
if (wave.channels > 2)
|
||||
{
|
||||
WaveFormat(&wave, wave.sampleRate, wave.sampleSize, 2);
|
||||
TraceLog(WARNING, "[%s] WAV channels number (%i) not supported, converted to 2 channels", fileName, wave.channels);
|
||||
TraceLog(LOG_WARNING, "[%s] WAV channels number (%i) not supported, converted to 2 channels", fileName, wave.channels);
|
||||
}
|
||||
|
||||
// NOTE: subChunkSize comes in bytes, we need to translate it to number of samples
|
||||
wave.sampleCount = (wavData.subChunkSize/(wave.sampleSize/8))/wave.channels;
|
||||
|
||||
TraceLog(INFO, "[%s] WAV file loaded successfully (%i Hz, %i bit, %s)", fileName, wave.sampleRate, wave.sampleSize, (wave.channels == 1) ? "Mono" : "Stereo");
|
||||
TraceLog(LOG_INFO, "[%s] WAV file loaded successfully (%i Hz, %i bit, %s)", fileName, wave.sampleRate, wave.sampleSize, (wave.channels == 1) ? "Mono" : "Stereo");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1245,35 +1255,31 @@ static Wave LoadWAV(const char *fileName)
|
|||
// NOTE: Using stb_vorbis library
|
||||
static Wave LoadOGG(const char *fileName)
|
||||
{
|
||||
Wave wave;
|
||||
Wave wave = { 0 };
|
||||
|
||||
stb_vorbis *oggFile = stb_vorbis_open_filename(fileName, NULL, NULL);
|
||||
|
||||
if (oggFile == NULL)
|
||||
{
|
||||
TraceLog(WARNING, "[%s] OGG file could not be opened", fileName);
|
||||
wave.data = NULL;
|
||||
}
|
||||
if (oggFile == NULL) TraceLog(LOG_WARNING, "[%s] OGG file could not be opened", fileName);
|
||||
else
|
||||
{
|
||||
stb_vorbis_info info = stb_vorbis_get_info(oggFile);
|
||||
|
||||
|
||||
wave.sampleRate = info.sample_rate;
|
||||
wave.sampleSize = 16; // 16 bit per sample (short)
|
||||
wave.channels = info.channels;
|
||||
wave.sampleCount = (int)stb_vorbis_stream_length_in_samples(oggFile);
|
||||
wave.sampleCount = (int)stb_vorbis_stream_length_in_samples(oggFile); // Independent by channel
|
||||
|
||||
float totalSeconds = stb_vorbis_stream_length_in_seconds(oggFile);
|
||||
if (totalSeconds > 10) TraceLog(WARNING, "[%s] Ogg audio length is larger than 10 seconds (%f), that's a big file in memory, consider music streaming", fileName, totalSeconds);
|
||||
if (totalSeconds > 10) TraceLog(LOG_WARNING, "[%s] Ogg audio length is larger than 10 seconds (%f), that's a big file in memory, consider music streaming", fileName, totalSeconds);
|
||||
|
||||
wave.data = (short *)malloc(wave.sampleCount*wave.channels*sizeof(short));
|
||||
|
||||
// NOTE: Returns the number of samples to process (be careful! we ask for number of shorts!)
|
||||
int numSamplesOgg = stb_vorbis_get_samples_short_interleaved(oggFile, info.channels, (short *)wave.data, wave.sampleCount*wave.channels);
|
||||
|
||||
TraceLog(DEBUG, "[%s] Samples obtained: %i", fileName, numSamplesOgg);
|
||||
TraceLog(LOG_DEBUG, "[%s] Samples obtained: %i", fileName, numSamplesOgg);
|
||||
|
||||
TraceLog(INFO, "[%s] OGG file loaded successfully (%i Hz, %i bit, %s)", fileName, wave.sampleRate, wave.sampleSize, (wave.channels == 1) ? "Mono" : "Stereo");
|
||||
TraceLog(LOG_INFO, "[%s] OGG file loaded successfully (%i Hz, %i bit, %s)", fileName, wave.sampleRate, wave.sampleSize, (wave.channels == 1) ? "Mono" : "Stereo");
|
||||
|
||||
stb_vorbis_close(oggFile);
|
||||
}
|
||||
|
@ -1297,10 +1303,10 @@ static Wave LoadFLAC(const char *fileName)
|
|||
wave.sampleSize = 16;
|
||||
|
||||
// NOTE: Only support up to 2 channels (mono, stereo)
|
||||
if (wave.channels > 2) TraceLog(WARNING, "[%s] FLAC channels number (%i) not supported", fileName, wave.channels);
|
||||
if (wave.channels > 2) TraceLog(LOG_WARNING, "[%s] FLAC channels number (%i) not supported", fileName, wave.channels);
|
||||
|
||||
if (wave.data == NULL) TraceLog(WARNING, "[%s] FLAC data could not be loaded", fileName);
|
||||
else TraceLog(INFO, "[%s] FLAC file loaded successfully (%i Hz, %i bit, %s)", fileName, wave.sampleRate, wave.sampleSize, (wave.channels == 1) ? "Mono" : "Stereo");
|
||||
if (wave.data == NULL) TraceLog(LOG_WARNING, "[%s] FLAC data could not be loaded", fileName);
|
||||
else TraceLog(LOG_INFO, "[%s] FLAC file loaded successfully (%i Hz, %i bit, %s)", fileName, wave.sampleRate, wave.sampleSize, (wave.channels == 1) ? "Mono" : "Stereo");
|
||||
|
||||
return wave;
|
||||
}
|
||||
|
@ -1322,35 +1328,26 @@ bool IsFileExtension(const char *fileName, const char *ext)
|
|||
return result;
|
||||
}
|
||||
|
||||
// Outputs a trace log message (INFO, ERROR, WARNING)
|
||||
// NOTE: If a file has been init, output log is written there
|
||||
// Show trace log messages (LOG_INFO, LOG_WARNING, LOG_ERROR, LOG_DEBUG)
|
||||
void TraceLog(int msgType, const char *text, ...)
|
||||
{
|
||||
va_list args;
|
||||
int traceDebugMsgs = 0;
|
||||
|
||||
#ifdef DO_NOT_TRACE_DEBUG_MSGS
|
||||
traceDebugMsgs = 0;
|
||||
#endif
|
||||
va_start(args, text);
|
||||
|
||||
switch (msgType)
|
||||
{
|
||||
case INFO: fprintf(stdout, "INFO: "); break;
|
||||
case ERROR: fprintf(stdout, "ERROR: "); break;
|
||||
case WARNING: fprintf(stdout, "WARNING: "); break;
|
||||
case DEBUG: if (traceDebugMsgs) fprintf(stdout, "DEBUG: "); break;
|
||||
case LOG_INFO: fprintf(stdout, "INFO: "); break;
|
||||
case LOG_ERROR: fprintf(stdout, "ERROR: "); break;
|
||||
case LOG_WARNING: fprintf(stdout, "WARNING: "); break;
|
||||
case LOG_DEBUG: fprintf(stdout, "DEBUG: "); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
if ((msgType != DEBUG) || ((msgType == DEBUG) && (traceDebugMsgs)))
|
||||
{
|
||||
va_start(args, text);
|
||||
vfprintf(stdout, text, args);
|
||||
va_end(args);
|
||||
vfprintf(stdout, text, args);
|
||||
fprintf(stdout, "\n");
|
||||
|
||||
fprintf(stdout, "\n");
|
||||
}
|
||||
va_end(args);
|
||||
|
||||
if (msgType == ERROR) exit(1); // If ERROR message, exit program
|
||||
if (msgType == LOG_ERROR) exit(1);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -181,7 +181,14 @@ void SetCameraMoveControls(int frontKey, int backKey,
|
|||
// Types and Structures Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
// Camera move modes (first person and third person cameras)
|
||||
typedef enum { MOVE_FRONT = 0, MOVE_BACK, MOVE_RIGHT, MOVE_LEFT, MOVE_UP, MOVE_DOWN } CameraMove;
|
||||
typedef enum {
|
||||
MOVE_FRONT = 0,
|
||||
MOVE_BACK,
|
||||
MOVE_RIGHT,
|
||||
MOVE_LEFT,
|
||||
MOVE_UP,
|
||||
MOVE_DOWN
|
||||
} CameraMove;
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Global Variables Definition
|
||||
|
@ -203,15 +210,14 @@ static int cameraMode = CAMERA_CUSTOM; // Current camera mode
|
|||
#if defined(CAMERA_STANDALONE)
|
||||
// NOTE: Camera controls depend on some raylib input functions
|
||||
// TODO: Set your own input functions (used in UpdateCamera())
|
||||
static Vector2 GetMousePosition() { return (Vector2){ 0.0f, 0.0f }; }
|
||||
static void SetMousePosition(Vector2 pos) {}
|
||||
static void EnableCursor() {} // Unlock cursor
|
||||
static void DisableCursor() {} // Lock cursor
|
||||
|
||||
static int IsKeyDown(int key) { return 0; }
|
||||
|
||||
static int IsMouseButtonDown(int button) { return 0;}
|
||||
static int GetMouseWheelMove() { return 0; }
|
||||
static int GetScreenWidth() { return 1280; }
|
||||
static int GetScreenHeight() { return 720; }
|
||||
static void ShowCursor() {}
|
||||
static void HideCursor() {}
|
||||
static int IsKeyDown(int key) { return 0; }
|
||||
static Vector2 GetMousePosition() { return (Vector2){ 0.0f, 0.0f }; }
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
|
@ -242,18 +248,23 @@ void SetCameraMode(Camera camera, int mode)
|
|||
cameraAngle.y = -asinf(fabsf(dy)/distance.y); // Camera angle in plane XY (0 aligned with X, move positive CW)
|
||||
|
||||
// NOTE: Just testing what cameraAngle means
|
||||
//cameraAngle.x = 0.0f*DEG2RAD; // Camera angle in plane XZ (0 aligned with Z, move positive CCW)
|
||||
//cameraAngle.x = 0.0f*DEG2RAD; // Camera angle in plane XZ (0 aligned with Z, move positive CCW)
|
||||
//cameraAngle.y = -60.0f*DEG2RAD; // Camera angle in plane XY (0 aligned with X, move positive CW)
|
||||
|
||||
playerEyesPosition = camera.position.y;
|
||||
|
||||
// Lock cursor for first person and third person cameras
|
||||
if ((mode == CAMERA_FIRST_PERSON) ||
|
||||
(mode == CAMERA_THIRD_PERSON)) DisableCursor();
|
||||
else EnableCursor();
|
||||
|
||||
cameraMode = mode;
|
||||
}
|
||||
|
||||
// Update camera depending on selected mode
|
||||
// NOTE: Camera controls depend on some raylib functions:
|
||||
// Mouse: GetMousePosition(), SetMousePosition(), IsMouseButtonDown(), GetMouseWheelMove()
|
||||
// System: GetScreenWidth(), GetScreenHeight(), ShowCursor(), HideCursor()
|
||||
// System: EnableCursor(), DisableCursor()
|
||||
// Mouse: IsMouseButtonDown(), GetMousePosition(), GetMouseWheelMove()
|
||||
// Keys: IsKeyDown()
|
||||
// TODO: Port to quaternion-based camera
|
||||
void UpdateCamera(Camera *camera)
|
||||
|
@ -284,36 +295,10 @@ void UpdateCamera(Camera *camera)
|
|||
|
||||
if (cameraMode != CAMERA_CUSTOM)
|
||||
{
|
||||
// Get screen size
|
||||
int screenWidth = GetScreenWidth();
|
||||
int screenHeight = GetScreenHeight();
|
||||
|
||||
if ((cameraMode == CAMERA_FIRST_PERSON) ||
|
||||
(cameraMode == CAMERA_THIRD_PERSON))
|
||||
{
|
||||
HideCursor();
|
||||
mousePositionDelta.x = mousePosition.x - previousMousePosition.x;
|
||||
mousePositionDelta.y = mousePosition.y - previousMousePosition.y;
|
||||
|
||||
if (mousePosition.x < (float)screenHeight/3.0f) SetMousePosition((Vector2){ screenWidth - screenHeight/3, mousePosition.y });
|
||||
else if (mousePosition.y < (float)screenHeight/3.0f) SetMousePosition((Vector2){ mousePosition.x, screenHeight - screenHeight/3 });
|
||||
else if (mousePosition.x > (screenWidth - (float)screenHeight/3.0f)) SetMousePosition((Vector2){ screenHeight/3, mousePosition.y });
|
||||
else if (mousePosition.y > (screenHeight - (float)screenHeight/3.0f)) SetMousePosition((Vector2){ mousePosition.x, screenHeight/3 });
|
||||
else
|
||||
{
|
||||
mousePositionDelta.x = mousePosition.x - previousMousePosition.x;
|
||||
mousePositionDelta.y = mousePosition.y - previousMousePosition.y;
|
||||
}
|
||||
}
|
||||
else // CAMERA_FREE, CAMERA_ORBITAL
|
||||
{
|
||||
ShowCursor();
|
||||
|
||||
mousePositionDelta.x = mousePosition.x - previousMousePosition.x;
|
||||
mousePositionDelta.y = mousePosition.y - previousMousePosition.y;
|
||||
}
|
||||
|
||||
// NOTE: We GetMousePosition() again because it can be modified by a previous SetMousePosition() call
|
||||
// If using directly mousePosition variable we have problems on CAMERA_FIRST_PERSON and CAMERA_THIRD_PERSON
|
||||
previousMousePosition = GetMousePosition();
|
||||
previousMousePosition = mousePosition;
|
||||
}
|
||||
|
||||
// Support for multiple automatic camera modes
|
||||
|
|
688
raylib/core.c
688
raylib/core.c
File diff suppressed because it is too large
Load diff
|
@ -8,7 +8,6 @@ import "C"
|
|||
|
||||
import (
|
||||
"io"
|
||||
"reflect"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
|
@ -480,6 +479,13 @@ func SetWindowIcon(image Image) {
|
|||
C.SetWindowIcon(*cimage)
|
||||
}
|
||||
|
||||
// SetWindowTitle - Set title for window (only PLATFORM_DESKTOP)
|
||||
func SetWindowTitle(title string) {
|
||||
ctitle := C.CString(title)
|
||||
defer C.free(unsafe.Pointer(ctitle))
|
||||
C.SetWindowTitle(ctitle)
|
||||
}
|
||||
|
||||
// SetWindowPosition - Set window position on screen (only PLATFORM_DESKTOP)
|
||||
func SetWindowPosition(x, y int32) {
|
||||
cx := (C.int)(x)
|
||||
|
@ -620,48 +626,51 @@ func GetHexValue(color Color) int32 {
|
|||
|
||||
// ColorToFloat - Converts Color to float array and normalizes
|
||||
func ColorToFloat(color Color) []float32 {
|
||||
ccolor := color.cptr()
|
||||
ret := C.ColorToFloat(*ccolor)
|
||||
|
||||
var data []float32
|
||||
sliceHeader := (*reflect.SliceHeader)((unsafe.Pointer(&data)))
|
||||
sliceHeader.Cap = 4
|
||||
sliceHeader.Len = 4
|
||||
sliceHeader.Data = uintptr(unsafe.Pointer(ret))
|
||||
data := make([]float32, 0)
|
||||
data[0] = float32(color.R) / 255
|
||||
data[0] = float32(color.G) / 255
|
||||
data[0] = float32(color.B) / 255
|
||||
data[0] = float32(color.A) / 255
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
// VectorToFloat - Converts Vector3 to float array
|
||||
func VectorToFloat(vec Vector3) []float32 {
|
||||
cvec := vec.cptr()
|
||||
ret := C.VectorToFloat(*cvec)
|
||||
|
||||
var data []float32
|
||||
sliceHeader := (*reflect.SliceHeader)((unsafe.Pointer(&data)))
|
||||
sliceHeader.Cap = 3
|
||||
sliceHeader.Len = 3
|
||||
sliceHeader.Data = uintptr(unsafe.Pointer(ret))
|
||||
data := make([]float32, 0)
|
||||
data[0] = vec.X
|
||||
data[1] = vec.Y
|
||||
data[2] = vec.Z
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
// MatrixToFloat - Converts Matrix to float array
|
||||
func MatrixToFloat(mat Matrix) []float32 {
|
||||
cmat := mat.cptr()
|
||||
ret := C.MatrixToFloat(*cmat)
|
||||
data := make([]float32, 0)
|
||||
|
||||
var data []float32
|
||||
sliceHeader := (*reflect.SliceHeader)((unsafe.Pointer(&data)))
|
||||
sliceHeader.Cap = 16
|
||||
sliceHeader.Len = 16
|
||||
sliceHeader.Data = uintptr(unsafe.Pointer(ret))
|
||||
data[0] = mat.M0
|
||||
data[1] = mat.M4
|
||||
data[2] = mat.M8
|
||||
data[3] = mat.M12
|
||||
data[4] = mat.M1
|
||||
data[5] = mat.M5
|
||||
data[6] = mat.M9
|
||||
data[7] = mat.M13
|
||||
data[8] = mat.M2
|
||||
data[9] = mat.M6
|
||||
data[10] = mat.M10
|
||||
data[11] = mat.M14
|
||||
data[12] = mat.M3
|
||||
data[13] = mat.M7
|
||||
data[14] = mat.M11
|
||||
data[15] = mat.M15
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
// GetRandomValue - Returns a random value between min and max (both included)
|
||||
func GetRandomValue(min int32, max int32) int32 {
|
||||
func GetRandomValue(min, max int32) int32 {
|
||||
cmin := (C.int)(min)
|
||||
cmax := (C.int)(max)
|
||||
ret := C.GetRandomValue(cmin, cmax)
|
||||
|
@ -689,13 +698,15 @@ func SetConfigFlags(flags byte) {
|
|||
C.SetConfigFlags(cflags)
|
||||
}
|
||||
|
||||
// TakeScreenshot - Takes a screenshot and saves it in the same folder as executable
|
||||
func TakeScreenshot() {
|
||||
C.TakeScreenshot()
|
||||
// TakeScreenshot - Takes a screenshot of current screen (saved a .png)
|
||||
func TakeScreenshot(name string) {
|
||||
cname := C.CString(name)
|
||||
defer C.free(unsafe.Pointer(cname))
|
||||
C.TakeScreenshot(cname)
|
||||
}
|
||||
|
||||
// StorageSaveValue - Storage save integer value (to defined position)
|
||||
func StorageSaveValue(position int32, value int32) {
|
||||
func StorageSaveValue(position, value int32) {
|
||||
cposition := (C.int)(position)
|
||||
cvalue := (C.int)(value)
|
||||
C.StorageSaveValue(cposition, cvalue)
|
||||
|
@ -781,7 +792,7 @@ func GetGamepadName(gamepad int32) string {
|
|||
}
|
||||
|
||||
// IsGamepadButtonPressed - Detect if a gamepad button has been pressed once
|
||||
func IsGamepadButtonPressed(gamepad int32, button int32) bool {
|
||||
func IsGamepadButtonPressed(gamepad, button int32) bool {
|
||||
cgamepad := (C.int)(gamepad)
|
||||
cbutton := (C.int)(button)
|
||||
ret := C.IsGamepadButtonPressed(cgamepad, cbutton)
|
||||
|
@ -790,7 +801,7 @@ func IsGamepadButtonPressed(gamepad int32, button int32) bool {
|
|||
}
|
||||
|
||||
// IsGamepadButtonDown - Detect if a gamepad button is being pressed
|
||||
func IsGamepadButtonDown(gamepad int32, button int32) bool {
|
||||
func IsGamepadButtonDown(gamepad, button int32) bool {
|
||||
cgamepad := (C.int)(gamepad)
|
||||
cbutton := (C.int)(button)
|
||||
ret := C.IsGamepadButtonDown(cgamepad, cbutton)
|
||||
|
@ -799,7 +810,7 @@ func IsGamepadButtonDown(gamepad int32, button int32) bool {
|
|||
}
|
||||
|
||||
// IsGamepadButtonReleased - Detect if a gamepad button has been released once
|
||||
func IsGamepadButtonReleased(gamepad int32, button int32) bool {
|
||||
func IsGamepadButtonReleased(gamepad, button int32) bool {
|
||||
cgamepad := (C.int)(gamepad)
|
||||
cbutton := (C.int)(button)
|
||||
ret := C.IsGamepadButtonReleased(cgamepad, cbutton)
|
||||
|
@ -808,7 +819,7 @@ func IsGamepadButtonReleased(gamepad int32, button int32) bool {
|
|||
}
|
||||
|
||||
// IsGamepadButtonUp - Detect if a gamepad button is NOT being pressed
|
||||
func IsGamepadButtonUp(gamepad int32, button int32) bool {
|
||||
func IsGamepadButtonUp(gamepad, button int32) bool {
|
||||
cgamepad := (C.int)(gamepad)
|
||||
cbutton := (C.int)(button)
|
||||
ret := C.IsGamepadButtonUp(cgamepad, cbutton)
|
||||
|
@ -832,7 +843,7 @@ func GetGamepadAxisCount(gamepad int32) int32 {
|
|||
}
|
||||
|
||||
// GetGamepadAxisMovement - Return axis movement value for a gamepad axis
|
||||
func GetGamepadAxisMovement(gamepad int32, axis int32) float32 {
|
||||
func GetGamepadAxisMovement(gamepad, axis int32) float32 {
|
||||
cgamepad := (C.int)(gamepad)
|
||||
caxis := (C.int)(axis)
|
||||
ret := C.GetGamepadAxisMovement(cgamepad, caxis)
|
||||
|
|
2050
raylib/external/par_shapes.h
vendored
Normal file
2050
raylib/external/par_shapes.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
913
raylib/external/rgif.h
vendored
Normal file
913
raylib/external/rgif.h
vendored
Normal file
|
@ -0,0 +1,913 @@
|
|||
/**********************************************************************************************
|
||||
*
|
||||
* rgif.h original implementation by Charlie Tangora [ctangora -at- gmail -dot- com]
|
||||
* adapted to C99, reformatted and renamed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* This file offers a simple, very limited way to create animated GIFs directly in code.
|
||||
*
|
||||
* Those looking for particular cleverness are likely to be disappointed; it's pretty
|
||||
* much a straight-ahead implementation of the GIF format with optional Floyd-Steinberg
|
||||
* dithering. (It does at least use delta encoding - only the changed portions of each
|
||||
* frame are saved.)
|
||||
*
|
||||
* So resulting files are often quite large. The hope is that it will be handy nonetheless
|
||||
* as a quick and easily-integrated way for programs to spit out animations.
|
||||
*
|
||||
* Only RGBA8 is currently supported as an input format. (The alpha is ignored.)
|
||||
*
|
||||
* CONFIGURATION:
|
||||
*
|
||||
* #define RGIF_IMPLEMENTATION
|
||||
* Generates the implementation of the library into the included file.
|
||||
* If not defined, the library is in header only mode and can be included in other headers
|
||||
* or source files without problems. But only ONE file should hold the implementation.
|
||||
*
|
||||
* USAGE:
|
||||
* 1) Create a GifWriter struct. Pass it to GifBegin() to initialize and write the header.
|
||||
* 2) Pass subsequent frames to GifWriteFrame().
|
||||
* 3) Finally, call GifEnd() to close the file handle and free memory.
|
||||
*
|
||||
*
|
||||
* LICENSE: public domain (www.unlicense.org)
|
||||
*
|
||||
* This is free and unencumbered software released into the public domain.
|
||||
* Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
|
||||
* software, either in source code form or as a compiled binary, for any purpose,
|
||||
* commercial or non-commercial, and by any means.
|
||||
*
|
||||
* In jurisdictions that recognize copyright laws, the author or authors of this
|
||||
* software dedicate any and all copyright interest in the software to the public
|
||||
* domain. We make this dedication for the benefit of the public at large and to
|
||||
* the detriment of our heirs and successors. We intend this dedication to be an
|
||||
* overt act of relinquishment in perpetuity of all present and future rights to
|
||||
* this software under copyright law.
|
||||
*
|
||||
* 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 THE
|
||||
* AUTHORS 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.
|
||||
*
|
||||
**********************************************************************************************/
|
||||
|
||||
#ifndef GIF_H
|
||||
#define GIF_H
|
||||
|
||||
#include <stdio.h> // Required for: FILE
|
||||
|
||||
//#define RGIF_STATIC
|
||||
#ifdef RGIF_STATIC
|
||||
#define RGIFDEF static // Functions just visible to module including this file
|
||||
#else
|
||||
#ifdef __cplusplus
|
||||
#define RGIFDEF extern "C" // Functions visible from other files (no name mangling of functions in C++)
|
||||
#else
|
||||
#define RGIFDEF extern // Functions visible from other files
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module Functions Declaration
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// NOTE: By default use bitDepth = 8, dither = false
|
||||
RGIFDEF bool GifBegin(const char *filename, unsigned int width, unsigned int height, unsigned int delay, unsigned int bitDepth, bool dither);
|
||||
RGIFDEF bool GifWriteFrame(const unsigned char *image, unsigned int width, unsigned int height, unsigned int delay, int bitDepth, bool dither);
|
||||
RGIFDEF bool GifEnd();
|
||||
|
||||
#endif // GIF_H
|
||||
|
||||
|
||||
/***********************************************************************************
|
||||
*
|
||||
* GIF IMPLEMENTATION
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#if defined(RGIF_IMPLEMENTATION)
|
||||
|
||||
#include <stdio.h> // Required for: FILE, fopen(), fclose()
|
||||
#include <string.h> // Required for: memcpy()
|
||||
|
||||
// Define these macros to hook into a custom memory allocator.
|
||||
// GIF_TEMP_MALLOC and GIF_TEMP_FREE will only be called in stack fashion - frees in the reverse order of mallocs
|
||||
// and any temp memory allocated by a function will be freed before it exits.
|
||||
#if !defined(GIF_TEMP_MALLOC)
|
||||
#include <stdlib.h>
|
||||
|
||||
#define GIF_TEMP_MALLOC malloc
|
||||
#define GIF_TEMP_FREE free
|
||||
#endif
|
||||
|
||||
// Check if custom malloc/free functions defined, if not, using standard ones
|
||||
// GIF_MALLOC and GIF_FREE are used only by GifBegin and GifEnd respectively,
|
||||
// to allocate a buffer the size of the image, which is used to find changed pixels for delta-encoding.
|
||||
#if !defined(GIF_MALLOC)
|
||||
#include <stdlib.h> // Required for: malloc(), free()
|
||||
|
||||
#define GIF_MALLOC(size) malloc(size)
|
||||
#define GIF_FREE(ptr) free(ptr)
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Defines and Macros
|
||||
//----------------------------------------------------------------------------------
|
||||
#define GIFMIN(a, b) (((a)<(b))?(a):(b))
|
||||
#define GIFMAX(a, b) (((a)>(b))?(a):(b))
|
||||
#define GIFABS(x) ((x)<0?-(x):(x))
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Types and Structures Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Gif palette structure
|
||||
typedef struct GifPalette {
|
||||
int bitDepth;
|
||||
|
||||
unsigned char r[256];
|
||||
unsigned char g[256];
|
||||
unsigned char b[256];
|
||||
|
||||
// k-d tree over RGB space, organized in heap fashion
|
||||
// i.e. left child of node i is node i*2, right child is node i*2 + 1
|
||||
// nodes 256-511 are implicitly the leaves, containing a color
|
||||
unsigned char treeSplitElt[255];
|
||||
unsigned char treeSplit[255];
|
||||
} GifPalette;
|
||||
|
||||
|
||||
// Simple structure to write out the LZW-compressed
|
||||
// portion of the imageone bit at a time
|
||||
typedef struct GifBitStatus {
|
||||
unsigned char bitIndex; // how many bits in the partial byte written so far
|
||||
unsigned char byte; // current partial byte
|
||||
|
||||
unsigned int chunkIndex;
|
||||
unsigned char chunk[256]; // bytes are written in here until we have 256 of them, then written to the file
|
||||
} GifBitStatus;
|
||||
|
||||
// The LZW dictionary is a 256-ary tree constructed
|
||||
// as the file is encoded, this is one node
|
||||
typedef struct GifLzwNode {
|
||||
uint16_t m_next[256];
|
||||
} GifLzwNode;
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Global Variables Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
const int gifTransparentIndex = 0; // Transparent color index
|
||||
|
||||
static FILE *gifFile;
|
||||
unsigned char *gifFrame;
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module specific Functions Declaration
|
||||
//----------------------------------------------------------------------------------
|
||||
static void GifGetClosestPaletteColor(GifPalette *pPal, int r, int g, int b, int *bestInd, int *bestDiff, int treeRoot);
|
||||
static void GifSwapPixels(unsigned char *image, int pixA, int pixB);
|
||||
static int GifPartition(unsigned char *image, const int left, const int right, const int elt, int pivotIndex);
|
||||
static void GifPartitionByMedian(unsigned char *image, int left, int right, int com, int neededCenter);
|
||||
static void GifSplitPalette(unsigned char *image, int numPixels, int firstElt, int lastElt, int splitElt, int splitDist, int treeNode, bool buildForDither, GifPalette *pal);
|
||||
static int GifPickChangedPixels(const unsigned char *lastFrame, unsigned char *frame, int numPixels);
|
||||
static void GifMakePalette(const unsigned char *lastFrame, const unsigned char *nextFrame, unsigned int width, unsigned int height, int bitDepth, bool buildForDither, GifPalette *pPal);
|
||||
static void GifDitherImage(const unsigned char *lastFrame, const unsigned char *nextFrame, unsigned char *outFrame, unsigned int width, unsigned int height, GifPalette *pPal);
|
||||
static void GifThresholdImage(const unsigned char *lastFrame, const unsigned char *nextFrame, unsigned char *outFrame, unsigned int width, unsigned int height, GifPalette *pPal);
|
||||
static void GifWriteBit(GifBitStatus *stat, unsigned int bit);
|
||||
static void GifWriteChunk(FILE *f, GifBitStatus *stat);
|
||||
static void GifWriteCode(FILE *f, GifBitStatus *stat, unsigned int code, unsigned int length);
|
||||
static void GifWritePalette(const GifPalette *pPal, FILE *f);
|
||||
static void GifWriteLzwImage(FILE *f, unsigned char *image, unsigned int left, unsigned int top, unsigned int width, unsigned int height, unsigned int delay, GifPalette *pPal);
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module Functions Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Creates a gif file
|
||||
// NOTE: Initializes internal file pointer (only one gif recording at a time)
|
||||
// The delay value is the time between frames in hundredths of a second - note that not all viewers pay much attention to this value.
|
||||
RGIFDEF bool GifBegin(const char *filename, unsigned int width, unsigned int height, unsigned int delay, unsigned int bitDepth, bool dither)
|
||||
{
|
||||
#if _MSC_VER >= 1400
|
||||
gifFile = 0;
|
||||
fopen_s(&gifFile, filename, "wb");
|
||||
#else
|
||||
gifFile = fopen(filename, "wb");
|
||||
#endif
|
||||
|
||||
if (!gifFile) return false;
|
||||
|
||||
// Allocate space for one gif frame
|
||||
gifFrame = (unsigned char *)GIF_MALLOC(width*height*4);
|
||||
|
||||
// GIF Header
|
||||
fputs("GIF89a",gifFile);
|
||||
|
||||
// Reference: http://www.onicos.com/staff/iz/formats/gif.html
|
||||
|
||||
// GIF Screen Descriptor
|
||||
fputc(width & 0xff, gifFile);
|
||||
fputc((width >> 8) & 0xff, gifFile); // Screen width (2 byte)
|
||||
fputc(height & 0xff, gifFile);
|
||||
fputc((height >> 8) & 0xff, gifFile); // Screen height (2 byte)
|
||||
|
||||
fputc(0xf0, gifFile); // Color table flags: unsorted global color table of 2 entries (1 byte, bit-flags)
|
||||
fputc(0, gifFile); // Background color index
|
||||
fputc(0, gifFile); // Pixel Aspect Ratio (square, we need to specify this because it's 1989)
|
||||
|
||||
// GIF Global Color table (just a dummy palette)
|
||||
// Color 0: black
|
||||
fputc(0, gifFile);
|
||||
fputc(0, gifFile);
|
||||
fputc(0, gifFile);
|
||||
// Color 1: also black
|
||||
fputc(0, gifFile);
|
||||
fputc(0, gifFile);
|
||||
fputc(0, gifFile);
|
||||
|
||||
if (delay != 0)
|
||||
{
|
||||
// Application Extension Block (19 bytes long)
|
||||
fputc(0x21, gifFile); // GIF Extension code
|
||||
fputc(0xff, gifFile); // Application Extension Label
|
||||
fputc(11, gifFile); // Length of Application Block (11 byte)
|
||||
fputs("NETSCAPE2.0", gifFile); // Application Identifier (Netscape 2.0 block)
|
||||
|
||||
fputc(0x03, gifFile); // Length of Data Sub-Block (3 bytes)
|
||||
fputc(0x01, gifFile); // 0x01
|
||||
fputc(0x00, gifFile); // This specifies the number of times,
|
||||
fputc(0x00, gifFile); // the loop should be executed (infinitely)
|
||||
|
||||
fputc(0x00, gifFile); // Data Sub-Block Terminator.
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Writes out a new frame to a GIF in progress.
|
||||
// NOTE: gifFile should have been initialized with GifBegin()
|
||||
// AFAIK, it is legal to use different bit depths for different frames of an image -
|
||||
// this may be handy to save bits in animations that don't change much.
|
||||
RGIFDEF bool GifWriteFrame(const unsigned char *image, unsigned int width, unsigned int height, unsigned int delay, int bitDepth, bool dither)
|
||||
{
|
||||
if (!gifFile) return false;
|
||||
|
||||
const unsigned char *oldImage = gifFrame;
|
||||
|
||||
GifPalette pal;
|
||||
GifMakePalette((dither ? NULL : oldImage), image, width, height, bitDepth, dither, &pal);
|
||||
|
||||
if (dither) GifDitherImage(oldImage, image, gifFrame, width, height, &pal);
|
||||
else GifThresholdImage(oldImage, image, gifFrame, width, height, &pal);
|
||||
|
||||
GifWriteLzwImage(gifFile, gifFrame, 0, 0, width, height, delay, &pal);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Writes the EOF code, closes the file handle, and frees temp memory used by a GIF.
|
||||
// Many if not most viewers will still display a GIF properly if the EOF code is missing,
|
||||
// but it's still a good idea to write it out.
|
||||
RGIFDEF bool GifEnd()
|
||||
{
|
||||
if (!gifFile) return false;
|
||||
|
||||
fputc(0x3b, gifFile); // Trailer (end of file)
|
||||
fclose(gifFile);
|
||||
|
||||
GIF_FREE(gifFrame);
|
||||
|
||||
gifFile = NULL;
|
||||
gifFrame = NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module specific Functions Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
// walks the k-d tree to pick the palette entry for a desired color.
|
||||
// Takes as in/out parameters the current best color and its error -
|
||||
// only changes them if it finds a better color in its subtree.
|
||||
// this is the major hotspot in the code at the moment.
|
||||
static void GifGetClosestPaletteColor(GifPalette *pPal, int r, int g, int b, int *bestInd, int *bestDiff, int treeRoot)
|
||||
{
|
||||
// base case, reached the bottom of the tree
|
||||
if (treeRoot > (1<<pPal->bitDepth)-1)
|
||||
{
|
||||
int ind = treeRoot-(1<<pPal->bitDepth);
|
||||
if (ind == gifTransparentIndex) return;
|
||||
|
||||
// check whether this color is better than the current winner
|
||||
int r_err = r - ((int32_t)pPal->r[ind]);
|
||||
int g_err = g - ((int32_t)pPal->g[ind]);
|
||||
int b_err = b - ((int32_t)pPal->b[ind]);
|
||||
int diff = GIFABS(r_err)+GIFABS(g_err)+GIFABS(b_err);
|
||||
|
||||
if (diff < *bestDiff)
|
||||
{
|
||||
*bestInd = ind;
|
||||
*bestDiff = diff;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// take the appropriate color (r, g, or b) for this node of the k-d tree
|
||||
int comps[3]; comps[0] = r; comps[1] = g; comps[2] = b;
|
||||
int splitComp = comps[pPal->treeSplitElt[treeRoot]];
|
||||
|
||||
int splitPos = pPal->treeSplit[treeRoot];
|
||||
if (splitPos > splitComp)
|
||||
{
|
||||
// check the left subtree
|
||||
GifGetClosestPaletteColor(pPal, r, g, b, bestInd, bestDiff, treeRoot*2);
|
||||
|
||||
if (*bestDiff > (splitPos - splitComp))
|
||||
{
|
||||
// cannot prove there's not a better value in the right subtree, check that too
|
||||
GifGetClosestPaletteColor(pPal, r, g, b, bestInd, bestDiff, treeRoot*2 + 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GifGetClosestPaletteColor(pPal, r, g, b, bestInd, bestDiff, treeRoot*2 + 1);
|
||||
|
||||
if (*bestDiff > splitComp - splitPos)
|
||||
{
|
||||
GifGetClosestPaletteColor(pPal, r, g, b, bestInd, bestDiff, treeRoot*2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void GifSwapPixels(unsigned char *image, int pixA, int pixB)
|
||||
{
|
||||
unsigned char rA = image[pixA*4];
|
||||
unsigned char gA = image[pixA*4 + 1];
|
||||
unsigned char bA = image[pixA*4+2];
|
||||
unsigned char aA = image[pixA*4+3];
|
||||
|
||||
unsigned char rB = image[pixB*4];
|
||||
unsigned char gB = image[pixB*4 + 1];
|
||||
unsigned char bB = image[pixB*4+2];
|
||||
unsigned char aB = image[pixA*4+3];
|
||||
|
||||
image[pixA*4] = rB;
|
||||
image[pixA*4 + 1] = gB;
|
||||
image[pixA*4+2] = bB;
|
||||
image[pixA*4+3] = aB;
|
||||
|
||||
image[pixB*4] = rA;
|
||||
image[pixB*4 + 1] = gA;
|
||||
image[pixB*4+2] = bA;
|
||||
image[pixB*4+3] = aA;
|
||||
}
|
||||
|
||||
// just the partition operation from quicksort
|
||||
static int GifPartition(unsigned char *image, const int left, const int right, const int elt, int pivotIndex)
|
||||
{
|
||||
const int pivotValue = image[(pivotIndex)*4+elt];
|
||||
GifSwapPixels(image, pivotIndex, right-1);
|
||||
int storeIndex = left;
|
||||
bool split = 0;
|
||||
for (int ii=left; ii<right-1; ++ii)
|
||||
{
|
||||
int arrayVal = image[ii*4+elt];
|
||||
if (arrayVal < pivotValue)
|
||||
{
|
||||
GifSwapPixels(image, ii, storeIndex);
|
||||
++storeIndex;
|
||||
}
|
||||
else if (arrayVal == pivotValue)
|
||||
{
|
||||
if (split)
|
||||
{
|
||||
GifSwapPixels(image, ii, storeIndex);
|
||||
++storeIndex;
|
||||
}
|
||||
split = !split;
|
||||
}
|
||||
}
|
||||
GifSwapPixels(image, storeIndex, right-1);
|
||||
return storeIndex;
|
||||
}
|
||||
|
||||
// Perform an incomplete sort, finding all elements above and below the desired median
|
||||
static void GifPartitionByMedian(unsigned char *image, int left, int right, int com, int neededCenter)
|
||||
{
|
||||
if (left < right-1)
|
||||
{
|
||||
int pivotIndex = left + (right-left)/2;
|
||||
|
||||
pivotIndex = GifPartition(image, left, right, com, pivotIndex);
|
||||
|
||||
// Only "sort" the section of the array that contains the median
|
||||
if (pivotIndex > neededCenter)
|
||||
GifPartitionByMedian(image, left, pivotIndex, com, neededCenter);
|
||||
|
||||
if (pivotIndex < neededCenter)
|
||||
GifPartitionByMedian(image, pivotIndex + 1, right, com, neededCenter);
|
||||
}
|
||||
}
|
||||
|
||||
// Builds a palette by creating a balanced k-d tree of all pixels in the image
|
||||
static void GifSplitPalette(unsigned char *image, int numPixels, int firstElt, int lastElt, int splitElt, int splitDist,
|
||||
int treeNode, bool buildForDither, GifPalette *pal)
|
||||
{
|
||||
if (lastElt <= firstElt || numPixels == 0)
|
||||
return;
|
||||
|
||||
// base case, bottom of the tree
|
||||
if (lastElt == firstElt + 1)
|
||||
{
|
||||
if (buildForDither)
|
||||
{
|
||||
// Dithering needs at least one color as dark as anything
|
||||
// in the image and at least one brightest color -
|
||||
// otherwise it builds up error and produces strange artifacts
|
||||
if (firstElt == 1)
|
||||
{
|
||||
// special case: the darkest color in the image
|
||||
unsigned int r=255, g=255, b=255;
|
||||
for (int ii=0; ii<numPixels; ++ii)
|
||||
{
|
||||
r = GIFMIN(r, image[ii*4+0]);
|
||||
g = GIFMIN(g, image[ii*4 + 1]);
|
||||
b = GIFMIN(b, image[ii*4+2]);
|
||||
}
|
||||
|
||||
pal->r[firstElt] = r;
|
||||
pal->g[firstElt] = g;
|
||||
pal->b[firstElt] = b;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (firstElt == (1 << pal->bitDepth)-1)
|
||||
{
|
||||
// special case: the lightest color in the image
|
||||
unsigned int r=0, g=0, b=0;
|
||||
for (int ii=0; ii<numPixels; ++ii)
|
||||
{
|
||||
r = GIFMAX(r, image[ii*4+0]);
|
||||
g = GIFMAX(g, image[ii*4 + 1]);
|
||||
b = GIFMAX(b, image[ii*4+2]);
|
||||
}
|
||||
|
||||
pal->r[firstElt] = r;
|
||||
pal->g[firstElt] = g;
|
||||
pal->b[firstElt] = b;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// otherwise, take the average of all colors in this subcube
|
||||
uint64_t r=0, g=0, b=0;
|
||||
for (int ii=0; ii<numPixels; ++ii)
|
||||
{
|
||||
r += image[ii*4+0];
|
||||
g += image[ii*4 + 1];
|
||||
b += image[ii*4+2];
|
||||
}
|
||||
|
||||
r += numPixels / 2; // round to nearest
|
||||
g += numPixels / 2;
|
||||
b += numPixels / 2;
|
||||
|
||||
r /= numPixels;
|
||||
g /= numPixels;
|
||||
b /= numPixels;
|
||||
|
||||
pal->r[firstElt] = (unsigned char)r;
|
||||
pal->g[firstElt] = (unsigned char)g;
|
||||
pal->b[firstElt] = (unsigned char)b;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Find the axis with the largest range
|
||||
int minR = 255, maxR = 0;
|
||||
int minG = 255, maxG = 0;
|
||||
int minB = 255, maxB = 0;
|
||||
for (int ii=0; ii<numPixels; ++ii)
|
||||
{
|
||||
int r = image[ii*4+0];
|
||||
int g = image[ii*4 + 1];
|
||||
int b = image[ii*4+2];
|
||||
|
||||
if (r > maxR) maxR = r;
|
||||
if (r < minR) minR = r;
|
||||
|
||||
if (g > maxG) maxG = g;
|
||||
if (g < minG) minG = g;
|
||||
|
||||
if (b > maxB) maxB = b;
|
||||
if (b < minB) minB = b;
|
||||
}
|
||||
|
||||
int rRange = maxR - minR;
|
||||
int gRange = maxG - minG;
|
||||
int bRange = maxB - minB;
|
||||
|
||||
// and split along that axis. (incidentally, this means this isn't a "proper" k-d tree but I don't know what else to call it)
|
||||
int splitCom = 1;
|
||||
if (bRange > gRange) splitCom = 2;
|
||||
if (rRange > bRange && rRange > gRange) splitCom = 0;
|
||||
|
||||
int subPixelsA = numPixels *(splitElt - firstElt) / (lastElt - firstElt);
|
||||
int subPixelsB = numPixels-subPixelsA;
|
||||
|
||||
GifPartitionByMedian(image, 0, numPixels, splitCom, subPixelsA);
|
||||
|
||||
pal->treeSplitElt[treeNode] = splitCom;
|
||||
pal->treeSplit[treeNode] = image[subPixelsA*4+splitCom];
|
||||
|
||||
GifSplitPalette(image, subPixelsA, firstElt, splitElt, splitElt-splitDist, splitDist/2, treeNode*2, buildForDither, pal);
|
||||
GifSplitPalette(image+subPixelsA*4, subPixelsB, splitElt, lastElt, splitElt+splitDist, splitDist/2, treeNode*2 + 1, buildForDither, pal);
|
||||
}
|
||||
|
||||
// Finds all pixels that have changed from the previous image and
|
||||
// moves them to the fromt of th buffer.
|
||||
// This allows us to build a palette optimized for the colors of the
|
||||
// changed pixels only.
|
||||
static int GifPickChangedPixels(const unsigned char *lastFrame, unsigned char *frame, int numPixels)
|
||||
{
|
||||
int numChanged = 0;
|
||||
unsigned char *writeIter = frame;
|
||||
|
||||
for (int ii=0; ii<numPixels; ++ii)
|
||||
{
|
||||
if (lastFrame[0] != frame[0] ||
|
||||
lastFrame[1] != frame[1] ||
|
||||
lastFrame[2] != frame[2])
|
||||
{
|
||||
writeIter[0] = frame[0];
|
||||
writeIter[1] = frame[1];
|
||||
writeIter[2] = frame[2];
|
||||
++numChanged;
|
||||
writeIter += 4;
|
||||
}
|
||||
lastFrame += 4;
|
||||
frame += 4;
|
||||
}
|
||||
|
||||
return numChanged;
|
||||
}
|
||||
|
||||
// Creates a palette by placing all the image pixels in a k-d tree and then averaging the blocks at the bottom.
|
||||
// This is known as the "modified median split" technique
|
||||
static void GifMakePalette(const unsigned char *lastFrame, const unsigned char *nextFrame, unsigned int width, unsigned int height, int bitDepth, bool buildForDither, GifPalette *pPal)
|
||||
{
|
||||
pPal->bitDepth = bitDepth;
|
||||
|
||||
// SplitPalette is destructive (it sorts the pixels by color) so
|
||||
// we must create a copy of the image for it to destroy
|
||||
int imageSize = width*height*4*sizeof(unsigned char);
|
||||
unsigned char *destroyableImage = (unsigned char*)GIF_TEMP_MALLOC(imageSize);
|
||||
memcpy(destroyableImage, nextFrame, imageSize);
|
||||
|
||||
int numPixels = width*height;
|
||||
if (lastFrame)
|
||||
numPixels = GifPickChangedPixels(lastFrame, destroyableImage, numPixels);
|
||||
|
||||
const int lastElt = 1 << bitDepth;
|
||||
const int splitElt = lastElt/2;
|
||||
const int splitDist = splitElt/2;
|
||||
|
||||
GifSplitPalette(destroyableImage, numPixels, 1, lastElt, splitElt, splitDist, 1, buildForDither, pPal);
|
||||
|
||||
GIF_TEMP_FREE(destroyableImage);
|
||||
|
||||
// add the bottom node for the transparency index
|
||||
pPal->treeSplit[1 << (bitDepth-1)] = 0;
|
||||
pPal->treeSplitElt[1 << (bitDepth-1)] = 0;
|
||||
|
||||
pPal->r[0] = pPal->g[0] = pPal->b[0] = 0;
|
||||
}
|
||||
|
||||
// Implements Floyd-Steinberg dithering, writes palette value to alpha
|
||||
static void GifDitherImage(const unsigned char *lastFrame, const unsigned char *nextFrame, unsigned char *outFrame, unsigned int width, unsigned int height, GifPalette *pPal)
|
||||
{
|
||||
int numPixels = width*height;
|
||||
|
||||
// quantPixels initially holds color*256 for all pixels
|
||||
// The extra 8 bits of precision allow for sub-single-color error values
|
||||
// to be propagated
|
||||
int32_t *quantPixels = (int32_t*)GIF_TEMP_MALLOC(sizeof(int32_t)*numPixels*4);
|
||||
|
||||
for (int ii=0; ii<numPixels*4; ++ii)
|
||||
{
|
||||
unsigned char pix = nextFrame[ii];
|
||||
int32_t pix16 = (int32_t)pix*256;
|
||||
quantPixels[ii] = pix16;
|
||||
}
|
||||
|
||||
for (unsigned int yy=0; yy<height; ++yy)
|
||||
{
|
||||
for (unsigned int xx=0; xx<width; ++xx)
|
||||
{
|
||||
int32_t *nextPix = quantPixels + 4*(yy*width+xx);
|
||||
const unsigned char *lastPix = lastFrame? lastFrame + 4*(yy*width+xx) : NULL;
|
||||
|
||||
// Compute the colors we want (rounding to nearest)
|
||||
int32_t rr = (nextPix[0] + 127) / 256;
|
||||
int32_t gg = (nextPix[1] + 127) / 256;
|
||||
int32_t bb = (nextPix[2] + 127) / 256;
|
||||
|
||||
// if it happens that we want the color from last frame, then just write out
|
||||
// a transparent pixel
|
||||
if (lastFrame &&
|
||||
lastPix[0] == rr &&
|
||||
lastPix[1] == gg &&
|
||||
lastPix[2] == bb)
|
||||
{
|
||||
nextPix[0] = rr;
|
||||
nextPix[1] = gg;
|
||||
nextPix[2] = bb;
|
||||
nextPix[3] = gifTransparentIndex;
|
||||
continue;
|
||||
}
|
||||
|
||||
int32_t bestDiff = 1000000;
|
||||
int32_t bestInd = gifTransparentIndex;
|
||||
|
||||
// Search the palete
|
||||
GifGetClosestPaletteColor(pPal, rr, gg, bb, &bestInd, &bestDiff, 1);
|
||||
|
||||
// Write the result to the temp buffer
|
||||
int32_t r_err = nextPix[0] - (int32_t)(pPal->r[bestInd])*256;
|
||||
int32_t g_err = nextPix[1] - (int32_t)(pPal->g[bestInd])*256;
|
||||
int32_t b_err = nextPix[2] - (int32_t)(pPal->b[bestInd])*256;
|
||||
|
||||
nextPix[0] = pPal->r[bestInd];
|
||||
nextPix[1] = pPal->g[bestInd];
|
||||
nextPix[2] = pPal->b[bestInd];
|
||||
nextPix[3] = bestInd;
|
||||
|
||||
// Propagate the error to the four adjacent locations
|
||||
// that we haven't touched yet
|
||||
int quantloc_7 = (yy*width+xx + 1);
|
||||
int quantloc_3 = (yy*width+width+xx-1);
|
||||
int quantloc_5 = (yy*width+width+xx);
|
||||
int quantloc_1 = (yy*width+width+xx + 1);
|
||||
|
||||
if (quantloc_7 < numPixels)
|
||||
{
|
||||
int32_t *pix7 = quantPixels+4*quantloc_7;
|
||||
pix7[0] += GIFMAX(-pix7[0], r_err*7 / 16);
|
||||
pix7[1] += GIFMAX(-pix7[1], g_err*7 / 16);
|
||||
pix7[2] += GIFMAX(-pix7[2], b_err*7 / 16);
|
||||
}
|
||||
|
||||
if (quantloc_3 < numPixels)
|
||||
{
|
||||
int32_t *pix3 = quantPixels+4*quantloc_3;
|
||||
pix3[0] += GIFMAX(-pix3[0], r_err*3 / 16);
|
||||
pix3[1] += GIFMAX(-pix3[1], g_err*3 / 16);
|
||||
pix3[2] += GIFMAX(-pix3[2], b_err*3 / 16);
|
||||
}
|
||||
|
||||
if (quantloc_5 < numPixels)
|
||||
{
|
||||
int32_t *pix5 = quantPixels+4*quantloc_5;
|
||||
pix5[0] += GIFMAX(-pix5[0], r_err*5 / 16);
|
||||
pix5[1] += GIFMAX(-pix5[1], g_err*5 / 16);
|
||||
pix5[2] += GIFMAX(-pix5[2], b_err*5 / 16);
|
||||
}
|
||||
|
||||
if (quantloc_1 < numPixels)
|
||||
{
|
||||
int32_t *pix1 = quantPixels+4*quantloc_1;
|
||||
pix1[0] += GIFMAX(-pix1[0], r_err / 16);
|
||||
pix1[1] += GIFMAX(-pix1[1], g_err / 16);
|
||||
pix1[2] += GIFMAX(-pix1[2], b_err / 16);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Copy the palettized result to the output buffer
|
||||
for (int ii=0; ii<numPixels*4; ++ii)
|
||||
{
|
||||
outFrame[ii] = quantPixels[ii];
|
||||
}
|
||||
|
||||
GIF_TEMP_FREE(quantPixels);
|
||||
}
|
||||
|
||||
// Picks palette colors for the image using simple thresholding, no dithering
|
||||
static void GifThresholdImage(const unsigned char *lastFrame, const unsigned char *nextFrame, unsigned char *outFrame, unsigned int width, unsigned int height, GifPalette *pPal)
|
||||
{
|
||||
unsigned int numPixels = width*height;
|
||||
for (unsigned int ii=0; ii<numPixels; ++ii)
|
||||
{
|
||||
// if a previous color is available, and it matches the current color,
|
||||
// set the pixel to transparent
|
||||
if (lastFrame &&
|
||||
lastFrame[0] == nextFrame[0] &&
|
||||
lastFrame[1] == nextFrame[1] &&
|
||||
lastFrame[2] == nextFrame[2])
|
||||
{
|
||||
outFrame[0] = lastFrame[0];
|
||||
outFrame[1] = lastFrame[1];
|
||||
outFrame[2] = lastFrame[2];
|
||||
outFrame[3] = gifTransparentIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
// palettize the pixel
|
||||
int32_t bestDiff = 1000000;
|
||||
int32_t bestInd = 1;
|
||||
GifGetClosestPaletteColor(pPal, nextFrame[0], nextFrame[1], nextFrame[2], &bestInd, &bestDiff, 1);
|
||||
|
||||
// Write the resulting color to the output buffer
|
||||
outFrame[0] = pPal->r[bestInd];
|
||||
outFrame[1] = pPal->g[bestInd];
|
||||
outFrame[2] = pPal->b[bestInd];
|
||||
outFrame[3] = bestInd;
|
||||
}
|
||||
|
||||
if (lastFrame) lastFrame += 4;
|
||||
outFrame += 4;
|
||||
nextFrame += 4;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// insert a single bit
|
||||
static void GifWriteBit(GifBitStatus *stat, unsigned int bit)
|
||||
{
|
||||
bit = bit & 1;
|
||||
bit = bit << stat->bitIndex;
|
||||
stat->byte |= bit;
|
||||
|
||||
++stat->bitIndex;
|
||||
if (stat->bitIndex > 7)
|
||||
{
|
||||
// move the newly-finished byte to the chunk buffer
|
||||
stat->chunk[stat->chunkIndex++] = stat->byte;
|
||||
// and start a new byte
|
||||
stat->bitIndex = 0;
|
||||
stat->byte = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// write all bytes so far to the file
|
||||
static void GifWriteChunk(FILE *f, GifBitStatus *stat)
|
||||
{
|
||||
fputc(stat->chunkIndex, f);
|
||||
fwrite(stat->chunk, 1, stat->chunkIndex, f);
|
||||
|
||||
stat->bitIndex = 0;
|
||||
stat->byte = 0;
|
||||
stat->chunkIndex = 0;
|
||||
}
|
||||
|
||||
static void GifWriteCode(FILE *f, GifBitStatus *stat, unsigned int code, unsigned int length)
|
||||
{
|
||||
for (unsigned int ii=0; ii<length; ++ii)
|
||||
{
|
||||
GifWriteBit(stat, code);
|
||||
code = code >> 1;
|
||||
|
||||
if (stat->chunkIndex == 255)
|
||||
{
|
||||
GifWriteChunk(f, stat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// write a 256-color (8-bit) image palette to the file
|
||||
static void GifWritePalette(const GifPalette *pPal, FILE *f)
|
||||
{
|
||||
fputc(0, f); // first color: transparency
|
||||
fputc(0, f);
|
||||
fputc(0, f);
|
||||
|
||||
for (int ii=1; ii<(1 << pPal->bitDepth); ++ii)
|
||||
{
|
||||
unsigned int r = pPal->r[ii];
|
||||
unsigned int g = pPal->g[ii];
|
||||
unsigned int b = pPal->b[ii];
|
||||
|
||||
fputc(r, f);
|
||||
fputc(g, f);
|
||||
fputc(b, f);
|
||||
}
|
||||
}
|
||||
|
||||
// write the image header, LZW-compress and write out the image
|
||||
static void GifWriteLzwImage(FILE *f, unsigned char *image, unsigned int left, unsigned int top, unsigned int width, unsigned int height, unsigned int delay, GifPalette *pPal)
|
||||
{
|
||||
// graphics control extension
|
||||
fputc(0x21, f);
|
||||
fputc(0xf9, f);
|
||||
fputc(0x04, f);
|
||||
fputc(0x05, f); // leave prev frame in place, this frame has transparency
|
||||
fputc(delay & 0xff, f);
|
||||
fputc((delay >> 8) & 0xff, f);
|
||||
fputc(gifTransparentIndex, f); // transparent color index
|
||||
fputc(0, f);
|
||||
|
||||
fputc(0x2c, f); // image descriptor block
|
||||
|
||||
fputc(left & 0xff, f); // corner of image in canvas space
|
||||
fputc((left >> 8) & 0xff, f);
|
||||
fputc(top & 0xff, f);
|
||||
fputc((top >> 8) & 0xff, f);
|
||||
|
||||
fputc(width & 0xff, f); // width and height of image
|
||||
fputc((width >> 8) & 0xff, f);
|
||||
fputc(height & 0xff, f);
|
||||
fputc((height >> 8) & 0xff, f);
|
||||
|
||||
//fputc(0, f); // no local color table, no transparency
|
||||
//fputc(0x80, f); // no local color table, but transparency
|
||||
|
||||
fputc(0x80 + pPal->bitDepth-1, f); // local color table present, 2 ^ bitDepth entries
|
||||
GifWritePalette(pPal, f);
|
||||
|
||||
const int minCodeSize = pPal->bitDepth;
|
||||
const unsigned int clearCode = 1 << pPal->bitDepth;
|
||||
|
||||
fputc(minCodeSize, f); // min code size 8 bits
|
||||
|
||||
GifLzwNode *codetree = (GifLzwNode *)GIF_TEMP_MALLOC(sizeof(GifLzwNode)*4096);
|
||||
|
||||
memset(codetree, 0, sizeof(GifLzwNode)*4096);
|
||||
int32_t curCode = -1;
|
||||
unsigned int codeSize = minCodeSize + 1;
|
||||
unsigned int maxCode = clearCode + 1;
|
||||
|
||||
GifBitStatus stat;
|
||||
stat.byte = 0;
|
||||
stat.bitIndex = 0;
|
||||
stat.chunkIndex = 0;
|
||||
|
||||
GifWriteCode(f, &stat, clearCode, codeSize); // start with a fresh LZW dictionary
|
||||
|
||||
for (unsigned int yy=0; yy<height; ++yy)
|
||||
{
|
||||
for (unsigned int xx=0; xx<width; ++xx)
|
||||
{
|
||||
unsigned char nextValue = image[(yy*width+xx)*4+3];
|
||||
|
||||
// "loser mode" - no compression, every single code is followed immediately by a clear
|
||||
//WriteCode(f, stat, nextValue, codeSize);
|
||||
//WriteCode(f, stat, 256, codeSize);
|
||||
|
||||
if (curCode < 0)
|
||||
{
|
||||
// first value in a new run
|
||||
curCode = nextValue;
|
||||
}
|
||||
else if (codetree[curCode].m_next[nextValue])
|
||||
{
|
||||
// current run already in the dictionary
|
||||
curCode = codetree[curCode].m_next[nextValue];
|
||||
}
|
||||
else
|
||||
{
|
||||
// finish the current run, write a code
|
||||
GifWriteCode(f, &stat, curCode, codeSize);
|
||||
|
||||
// insert the new run into the dictionary
|
||||
codetree[curCode].m_next[nextValue] = ++maxCode;
|
||||
|
||||
if (maxCode >= (1ul << codeSize))
|
||||
{
|
||||
// dictionary entry count has broken a size barrier,
|
||||
// we need more bits for codes
|
||||
codeSize++;
|
||||
}
|
||||
if (maxCode == 4095)
|
||||
{
|
||||
// the dictionary is full, clear it out and begin anew
|
||||
GifWriteCode(f, &stat, clearCode, codeSize); // clear tree
|
||||
|
||||
memset(codetree, 0, sizeof(GifLzwNode)*4096);
|
||||
curCode = -1;
|
||||
codeSize = minCodeSize + 1;
|
||||
maxCode = clearCode + 1;
|
||||
}
|
||||
|
||||
curCode = nextValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// compression footer
|
||||
GifWriteCode(f, &stat, curCode, codeSize);
|
||||
GifWriteCode(f, &stat, clearCode, codeSize);
|
||||
GifWriteCode(f, &stat, clearCode + 1, minCodeSize + 1);
|
||||
|
||||
// write out the last partial chunk
|
||||
while (stat.bitIndex) GifWriteBit(&stat, 0);
|
||||
if (stat.chunkIndex) GifWriteChunk(f, &stat);
|
||||
|
||||
fputc(0, f); // image block terminator
|
||||
|
||||
GIF_TEMP_FREE(codetree);
|
||||
}
|
||||
|
||||
#endif // RGIF_IMPLEMENTATION
|
184
raylib/external/stb_image.h
vendored
184
raylib/external/stb_image.h
vendored
|
@ -1,4 +1,4 @@
|
|||
/* stb_image - v2.15 - public domain image loader - http://nothings.org/stb_image.h
|
||||
/* stb_image - v2.16 - public domain image loader - http://nothings.org/stb_image.h
|
||||
no warranty implied; use at your own risk
|
||||
|
||||
Do this:
|
||||
|
@ -48,6 +48,7 @@ LICENSE
|
|||
|
||||
RECENT REVISION HISTORY:
|
||||
|
||||
2.16 (2017-07-23) all functions have 16-bit variants; optimizations; bugfixes
|
||||
2.15 (2017-03-18) fix png-1,2,4; all Imagenet JPGs; no runtime SSE detection on GCC
|
||||
2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs
|
||||
2.13 (2016-12-04) experimental 16-bit API, only for PNG so far; fixes
|
||||
|
@ -58,10 +59,6 @@ RECENT REVISION HISTORY:
|
|||
correct channel count for PNG & BMP
|
||||
2.10 (2016-01-22) avoid warning introduced in 2.09
|
||||
2.09 (2016-01-16) 16-bit TGA; comments in PNM files; STBI_REALLOC_SIZED
|
||||
2.08 (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA
|
||||
2.07 (2015-09-13) partial animated GIF support
|
||||
limited 16-bit PSD support
|
||||
minor bugs, code cleanup, and compiler warnings
|
||||
|
||||
See end of file for full revision history.
|
||||
|
||||
|
@ -83,6 +80,7 @@ RECENT REVISION HISTORY:
|
|||
Optimizations & bugfixes
|
||||
Fabian "ryg" Giesen
|
||||
Arseny Kapoulkine
|
||||
John-Mark Allen
|
||||
|
||||
Bug & warning fixes
|
||||
Marc LeBlanc David Woo Guillaume George Martins Mozeiko
|
||||
|
@ -98,7 +96,7 @@ RECENT REVISION HISTORY:
|
|||
Michaelangel007@github Philipp Wiesemann Dale Weiler github:grim210
|
||||
Oriol Ferrer Mesia Josh Tobin Matthew Gregan github:sammyhw
|
||||
Blazej Dariusz Roszkowski Gregory Mullen github:phprus
|
||||
|
||||
Christian Floisand Kevin Schmidt github:poppolopoppo
|
||||
*/
|
||||
|
||||
#ifndef STBI_INCLUDE_STB_IMAGE_H
|
||||
|
@ -134,11 +132,12 @@ RECENT REVISION HISTORY:
|
|||
// with each pixel consisting of N interleaved 8-bit components; the first
|
||||
// pixel pointed to is top-left-most in the image. There is no padding between
|
||||
// image scanlines or between pixels, regardless of format. The number of
|
||||
// components N is 'req_comp' if req_comp is non-zero, or *comp otherwise.
|
||||
// If req_comp is non-zero, *comp has the number of components that _would_
|
||||
// have been output otherwise. E.g. if you set req_comp to 4, you will always
|
||||
// get RGBA output, but you can check *comp to see if it's trivially opaque
|
||||
// because e.g. there were only 3 channels in the source image.
|
||||
// components N is 'desired_channels' if desired_channels is non-zero, or
|
||||
// *channels_in_file otherwise. If desired_channels is non-zero,
|
||||
// *channels_in_file has the number of components that _would_ have been
|
||||
// output otherwise. E.g. if you set desired_channels to 4, you will always
|
||||
// get RGBA output, but you can check *channels_in_file to see if it's trivially
|
||||
// opaque because e.g. there were only 3 channels in the source image.
|
||||
//
|
||||
// An output image with N components has the following components interleaved
|
||||
// in this order in each pixel:
|
||||
|
@ -150,10 +149,10 @@ RECENT REVISION HISTORY:
|
|||
// 4 red, green, blue, alpha
|
||||
//
|
||||
// If image loading fails for any reason, the return value will be NULL,
|
||||
// and *x, *y, *comp will be unchanged. The function stbi_failure_reason()
|
||||
// can be queried for an extremely brief, end-user unfriendly explanation
|
||||
// of why the load failed. Define STBI_NO_FAILURE_STRINGS to avoid
|
||||
// compiling these strings at all, and STBI_FAILURE_USERMSG to get slightly
|
||||
// and *x, *y, *channels_in_file will be unchanged. The function
|
||||
// stbi_failure_reason() can be queried for an extremely brief, end-user
|
||||
// unfriendly explanation of why the load failed. Define STBI_NO_FAILURE_STRINGS
|
||||
// to avoid compiling these strings at all, and STBI_FAILURE_USERMSG to get slightly
|
||||
// more user-friendly ones.
|
||||
//
|
||||
// Paletted PNG, BMP, GIF, and PIC images are automatically depalettized.
|
||||
|
@ -310,7 +309,7 @@ RECENT REVISION HISTORY:
|
|||
|
||||
enum
|
||||
{
|
||||
STBI_default = 0, // only used for req_comp
|
||||
STBI_default = 0, // only used for desired_channels
|
||||
|
||||
STBI_grey = 1,
|
||||
STBI_grey_alpha = 2,
|
||||
|
@ -352,12 +351,12 @@ typedef struct
|
|||
// 8-bits-per-channel interface
|
||||
//
|
||||
|
||||
STBIDEF stbi_uc *stbi_load (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels);
|
||||
STBIDEF stbi_uc *stbi_load_from_memory (stbi_uc const *buffer, int len , int *x, int *y, int *channels_in_file, int desired_channels);
|
||||
STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk , void *user, int *x, int *y, int *channels_in_file, int desired_channels);
|
||||
|
||||
#ifndef STBI_NO_STDIO
|
||||
STBIDEF stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels);
|
||||
STBIDEF stbi_uc *stbi_load (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels);
|
||||
STBIDEF stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels);
|
||||
// for stbi_load_from_file, file pointer is left pointing immediately after image
|
||||
#endif
|
||||
|
||||
|
@ -366,22 +365,24 @@ STBIDEF stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *channels_i
|
|||
// 16-bits-per-channel interface
|
||||
//
|
||||
|
||||
STBIDEF stbi_us *stbi_load_16(char const *filename, int *x, int *y, int *channels_in_file, int desired_channels);
|
||||
STBIDEF stbi_us *stbi_load_16_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels);
|
||||
STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels);
|
||||
|
||||
#ifndef STBI_NO_STDIO
|
||||
STBIDEF stbi_us *stbi_load_16 (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels);
|
||||
STBIDEF stbi_us *stbi_load_from_file_16(FILE *f, int *x, int *y, int *channels_in_file, int desired_channels);
|
||||
#endif
|
||||
// @TODO the other variants
|
||||
|
||||
////////////////////////////////////
|
||||
//
|
||||
// float-per-channel interface
|
||||
//
|
||||
#ifndef STBI_NO_LINEAR
|
||||
STBIDEF float *stbi_loadf (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels);
|
||||
STBIDEF float *stbi_loadf_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels);
|
||||
STBIDEF float *stbi_loadf_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels);
|
||||
|
||||
#ifndef STBI_NO_STDIO
|
||||
STBIDEF float *stbi_loadf (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels);
|
||||
STBIDEF float *stbi_loadf_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels);
|
||||
#endif
|
||||
#endif
|
||||
|
@ -639,7 +640,7 @@ static int stbi__cpuid3(void)
|
|||
|
||||
#define STBI_SIMD_ALIGN(type, name) __declspec(align(16)) type name
|
||||
|
||||
static int stbi__sse2_available()
|
||||
static int stbi__sse2_available(void)
|
||||
{
|
||||
int info3 = stbi__cpuid3();
|
||||
return ((info3 >> 26) & 1) != 0;
|
||||
|
@ -647,7 +648,7 @@ static int stbi__sse2_available()
|
|||
#else // assume GCC-style if not VC++
|
||||
#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16)))
|
||||
|
||||
static int stbi__sse2_available()
|
||||
static int stbi__sse2_available(void)
|
||||
{
|
||||
// If we're even attempting to compile this on GCC/Clang, that means
|
||||
// -msse2 is on, which means the compiler is allowed to use SSE2
|
||||
|
@ -1029,6 +1030,30 @@ static stbi__uint16 *stbi__convert_8_to_16(stbi_uc *orig, int w, int h, int chan
|
|||
return enlarged;
|
||||
}
|
||||
|
||||
static void stbi__vertical_flip(void *image, int w, int h, int bytes_per_pixel)
|
||||
{
|
||||
int row;
|
||||
size_t bytes_per_row = (size_t)w * bytes_per_pixel;
|
||||
stbi_uc temp[2048];
|
||||
stbi_uc *bytes = (stbi_uc *)image;
|
||||
|
||||
for (row = 0; row < (h>>1); row++) {
|
||||
stbi_uc *row0 = bytes + row*bytes_per_row;
|
||||
stbi_uc *row1 = bytes + (h - row - 1)*bytes_per_row;
|
||||
// swap row0 with row1
|
||||
size_t bytes_left = bytes_per_row;
|
||||
while (bytes_left) {
|
||||
size_t bytes_copy = (bytes_left < sizeof(temp)) ? bytes_left : sizeof(temp);
|
||||
memcpy(temp, row0, bytes_copy);
|
||||
memcpy(row0, row1, bytes_copy);
|
||||
memcpy(row1, temp, bytes_copy);
|
||||
row0 += bytes_copy;
|
||||
row1 += bytes_copy;
|
||||
bytes_left -= bytes_copy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x, int *y, int *comp, int req_comp)
|
||||
{
|
||||
stbi__result_info ri;
|
||||
|
@ -1046,21 +1071,8 @@ static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x,
|
|||
// @TODO: move stbi__convert_format to here
|
||||
|
||||
if (stbi__vertically_flip_on_load) {
|
||||
int w = *x, h = *y;
|
||||
int channels = req_comp ? req_comp : *comp;
|
||||
int row,col,z;
|
||||
stbi_uc *image = (stbi_uc *) result;
|
||||
|
||||
// @OPTIMIZE: use a bigger temp buffer and memcpy multiple pixels at once
|
||||
for (row = 0; row < (h>>1); row++) {
|
||||
for (col = 0; col < w; col++) {
|
||||
for (z = 0; z < channels; z++) {
|
||||
stbi_uc temp = image[(row * w + col) * channels + z];
|
||||
image[(row * w + col) * channels + z] = image[((h - row - 1) * w + col) * channels + z];
|
||||
image[((h - row - 1) * w + col) * channels + z] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi_uc));
|
||||
}
|
||||
|
||||
return (unsigned char *) result;
|
||||
|
@ -1084,21 +1096,8 @@ static stbi__uint16 *stbi__load_and_postprocess_16bit(stbi__context *s, int *x,
|
|||
// @TODO: special case RGB-to-Y (and RGBA-to-YA) for 8-bit-to-16-bit case to keep more precision
|
||||
|
||||
if (stbi__vertically_flip_on_load) {
|
||||
int w = *x, h = *y;
|
||||
int channels = req_comp ? req_comp : *comp;
|
||||
int row,col,z;
|
||||
stbi__uint16 *image = (stbi__uint16 *) result;
|
||||
|
||||
// @OPTIMIZE: use a bigger temp buffer and memcpy multiple pixels at once
|
||||
for (row = 0; row < (h>>1); row++) {
|
||||
for (col = 0; col < w; col++) {
|
||||
for (z = 0; z < channels; z++) {
|
||||
stbi__uint16 temp = image[(row * w + col) * channels + z];
|
||||
image[(row * w + col) * channels + z] = image[((h - row - 1) * w + col) * channels + z];
|
||||
image[((h - row - 1) * w + col) * channels + z] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi__uint16));
|
||||
}
|
||||
|
||||
return (stbi__uint16 *) result;
|
||||
|
@ -1108,21 +1107,8 @@ static stbi__uint16 *stbi__load_and_postprocess_16bit(stbi__context *s, int *x,
|
|||
static void stbi__float_postprocess(float *result, int *x, int *y, int *comp, int req_comp)
|
||||
{
|
||||
if (stbi__vertically_flip_on_load && result != NULL) {
|
||||
int w = *x, h = *y;
|
||||
int depth = req_comp ? req_comp : *comp;
|
||||
int row,col,z;
|
||||
float temp;
|
||||
|
||||
// @OPTIMIZE: use a bigger temp buffer and memcpy multiple pixels at once
|
||||
for (row = 0; row < (h>>1); row++) {
|
||||
for (col = 0; col < w; col++) {
|
||||
for (z = 0; z < depth; z++) {
|
||||
temp = result[(row * w + col) * depth + z];
|
||||
result[(row * w + col) * depth + z] = result[((h - row - 1) * w + col) * depth + z];
|
||||
result[((h - row - 1) * w + col) * depth + z] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
int channels = req_comp ? req_comp : *comp;
|
||||
stbi__vertical_flip(result, *x, *y, channels * sizeof(float));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -1191,6 +1177,20 @@ STBIDEF stbi_us *stbi_load_16(char const *filename, int *x, int *y, int *comp, i
|
|||
|
||||
#endif //!STBI_NO_STDIO
|
||||
|
||||
STBIDEF stbi_us *stbi_load_16_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels)
|
||||
{
|
||||
stbi__context s;
|
||||
stbi__start_mem(&s,buffer,len);
|
||||
return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels);
|
||||
}
|
||||
|
||||
STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels)
|
||||
{
|
||||
stbi__context s;
|
||||
stbi__start_callbacks(&s, (stbi_io_callbacks *)clbk, user);
|
||||
return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels);
|
||||
}
|
||||
|
||||
STBIDEF stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp)
|
||||
{
|
||||
stbi__context s;
|
||||
|
@ -2806,7 +2806,7 @@ static int stbi__process_marker(stbi__jpeg *z, int m)
|
|||
if (t > 3) return stbi__err("bad DQT table","Corrupt JPEG");
|
||||
|
||||
for (i=0; i < 64; ++i)
|
||||
z->dequant[t][stbi__jpeg_dezigzag[i]] = sixteen ? stbi__get16be(z->s) : stbi__get8(z->s);
|
||||
z->dequant[t][stbi__jpeg_dezigzag[i]] = (stbi__uint16)(sixteen ? stbi__get16be(z->s) : stbi__get8(z->s));
|
||||
L -= (sixteen ? 129 : 65);
|
||||
}
|
||||
return L==0;
|
||||
|
@ -3611,20 +3611,20 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp
|
|||
} else if (z->s->img_n == 4) {
|
||||
if (z->app14_color_transform == 0) { // CMYK
|
||||
for (i=0; i < z->s->img_x; ++i) {
|
||||
stbi_uc k = coutput[3][i];
|
||||
out[0] = stbi__blinn_8x8(coutput[0][i], k);
|
||||
out[1] = stbi__blinn_8x8(coutput[1][i], k);
|
||||
out[2] = stbi__blinn_8x8(coutput[2][i], k);
|
||||
stbi_uc m = coutput[3][i];
|
||||
out[0] = stbi__blinn_8x8(coutput[0][i], m);
|
||||
out[1] = stbi__blinn_8x8(coutput[1][i], m);
|
||||
out[2] = stbi__blinn_8x8(coutput[2][i], m);
|
||||
out[3] = 255;
|
||||
out += n;
|
||||
}
|
||||
} else if (z->app14_color_transform == 2) { // YCCK
|
||||
z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n);
|
||||
for (i=0; i < z->s->img_x; ++i) {
|
||||
stbi_uc k = coutput[3][i];
|
||||
out[0] = stbi__blinn_8x8(255 - out[0], k);
|
||||
out[1] = stbi__blinn_8x8(255 - out[1], k);
|
||||
out[2] = stbi__blinn_8x8(255 - out[2], k);
|
||||
stbi_uc m = coutput[3][i];
|
||||
out[0] = stbi__blinn_8x8(255 - out[0], m);
|
||||
out[1] = stbi__blinn_8x8(255 - out[1], m);
|
||||
out[2] = stbi__blinn_8x8(255 - out[2], m);
|
||||
out += n;
|
||||
}
|
||||
} else { // YCbCr + alpha? Ignore the fourth channel for now
|
||||
|
@ -3649,10 +3649,10 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp
|
|||
}
|
||||
} else if (z->s->img_n == 4 && z->app14_color_transform == 0) {
|
||||
for (i=0; i < z->s->img_x; ++i) {
|
||||
stbi_uc k = coutput[3][i];
|
||||
stbi_uc r = stbi__blinn_8x8(coutput[0][i], k);
|
||||
stbi_uc g = stbi__blinn_8x8(coutput[1][i], k);
|
||||
stbi_uc b = stbi__blinn_8x8(coutput[2][i], k);
|
||||
stbi_uc m = coutput[3][i];
|
||||
stbi_uc r = stbi__blinn_8x8(coutput[0][i], m);
|
||||
stbi_uc g = stbi__blinn_8x8(coutput[1][i], m);
|
||||
stbi_uc b = stbi__blinn_8x8(coutput[2][i], m);
|
||||
out[0] = stbi__compute_y(r, g, b);
|
||||
out[1] = 255;
|
||||
out += n;
|
||||
|
@ -4297,11 +4297,10 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r
|
|||
|
||||
img_width_bytes = (((img_n * x * depth) + 7) >> 3);
|
||||
img_len = (img_width_bytes + 1) * y;
|
||||
if (s->img_x == x && s->img_y == y) {
|
||||
if (raw_len != img_len) return stbi__err("not enough pixels","Corrupt PNG");
|
||||
} else { // interlaced:
|
||||
if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG");
|
||||
}
|
||||
// we used to check for exact match between raw_len and img_len on non-interlaced PNGs,
|
||||
// but issue #276 reported a PNG in the wild that had extra data at the end (all zeros),
|
||||
// so just check for raw_len < img_len always.
|
||||
if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG");
|
||||
|
||||
for (j=0; j < y; ++j) {
|
||||
stbi_uc *cur = a->out + stride*j;
|
||||
|
@ -4654,9 +4653,10 @@ static void stbi__de_iphone(stbi__png *z)
|
|||
stbi_uc a = p[3];
|
||||
stbi_uc t = p[0];
|
||||
if (a) {
|
||||
p[0] = p[2] * 255 / a;
|
||||
p[1] = p[1] * 255 / a;
|
||||
p[2] = t * 255 / a;
|
||||
stbi_uc half = a / 2;
|
||||
p[0] = (p[2] * 255 + half) / a;
|
||||
p[1] = (p[1] * 255 + half) / a;
|
||||
p[2] = ( t * 255 + half) / a;
|
||||
} else {
|
||||
p[0] = p[2];
|
||||
p[2] = t;
|
||||
|
@ -4819,6 +4819,9 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
|
|||
if (req_comp >= 3) s->img_out_n = req_comp;
|
||||
if (!stbi__expand_png_palette(z, palette, pal_len, s->img_out_n))
|
||||
return 0;
|
||||
} else if (has_trans) {
|
||||
// non-paletted image with tRNS -> source image has (constant) alpha
|
||||
++s->img_n;
|
||||
}
|
||||
STBI_FREE(z->expanded); z->expanded = NULL;
|
||||
return 1;
|
||||
|
@ -6966,6 +6969,13 @@ STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int
|
|||
|
||||
/*
|
||||
revision history:
|
||||
2.16 (2017-07-23) all functions have 16-bit variants;
|
||||
STBI_NO_STDIO works again;
|
||||
compilation fixes;
|
||||
fix rounding in unpremultiply;
|
||||
optimize vertical flip;
|
||||
disable raw_len validation;
|
||||
documentation fixes
|
||||
2.15 (2017-03-18) fix png-1,2,4 bug; now all Imagenet JPGs decode;
|
||||
warning fixes; disable run-time SSE detection on gcc;
|
||||
uniform handling of optional "return" values;
|
||||
|
|
13
raylib/external/stb_image_resize.h
vendored
13
raylib/external/stb_image_resize.h
vendored
|
@ -1,4 +1,4 @@
|
|||
/* stb_image_resize - v0.94 - public domain image resizing
|
||||
/* stb_image_resize - v0.95 - public domain image resizing
|
||||
by Jorge L Rodriguez (@VinoBS) - 2014
|
||||
http://github.com/nothings/stb
|
||||
|
||||
|
@ -156,8 +156,10 @@
|
|||
Jorge L Rodriguez: Implementation
|
||||
Sean Barrett: API design, optimizations
|
||||
Aras Pranckevicius: bugfix
|
||||
|
||||
Nathan Reed: warning fixes
|
||||
|
||||
REVISIONS
|
||||
0.95 (2017-07-23) fixed warnings
|
||||
0.94 (2017-03-18) fixed warnings
|
||||
0.93 (2017-03-03) fixed bug with certain combinations of heights
|
||||
0.92 (2017-01-02) fix integer overflow on large (>2GB) images
|
||||
|
@ -393,8 +395,9 @@ STBIRDEF int stbir_resize_region( const void *input_pixels , int input_w , int
|
|||
|
||||
#ifndef STBIR_MALLOC
|
||||
#include <stdlib.h>
|
||||
#define STBIR_MALLOC(size,c) malloc(size)
|
||||
#define STBIR_FREE(ptr,c) free(ptr)
|
||||
// use comma operator to evaluate c, to avoid "unused parameter" warnings
|
||||
#define STBIR_MALLOC(size,c) ((void)(c), malloc(size))
|
||||
#define STBIR_FREE(ptr,c) ((void)(c), free(ptr))
|
||||
#endif
|
||||
|
||||
#ifndef _MSC_VER
|
||||
|
@ -983,7 +986,7 @@ static int stbir__edge_wrap_slow(stbir_edge edge, int n, int max)
|
|||
|
||||
return (m);
|
||||
}
|
||||
return n; // NOTREACHED
|
||||
// NOTREACHED
|
||||
|
||||
default:
|
||||
STBIR_ASSERT(!"Unimplemented edge type");
|
||||
|
|
378
raylib/external/stb_image_write.h
vendored
378
raylib/external/stb_image_write.h
vendored
|
@ -1,5 +1,5 @@
|
|||
/* stb_image_write - v1.05 - public domain - http://nothings.org/stb/stb_image_write.h
|
||||
writes out PNG/BMP/TGA images to C stdio - Sean Barrett 2010-2015
|
||||
/* stb_image_write - v1.07 - public domain - http://nothings.org/stb/stb_image_write.h
|
||||
writes out PNG/BMP/TGA/JPEG/HDR images to C stdio - Sean Barrett 2010-2015
|
||||
no warranty implied; use at your own risk
|
||||
|
||||
Before #including,
|
||||
|
@ -35,6 +35,7 @@ USAGE:
|
|||
int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data);
|
||||
int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data);
|
||||
int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data);
|
||||
int stbi_write_jpg(char const *filename, int w, int h, int comp, const float *data);
|
||||
|
||||
There are also four equivalent functions that use an arbitrary write function. You are
|
||||
expected to open/close your file-equivalent before and after calling these:
|
||||
|
@ -43,6 +44,7 @@ USAGE:
|
|||
int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data);
|
||||
int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data);
|
||||
int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data);
|
||||
int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality);
|
||||
|
||||
where the callback is:
|
||||
void stbi_write_func(void *context, void *data, int size);
|
||||
|
@ -79,6 +81,10 @@ USAGE:
|
|||
|
||||
TGA supports RLE or non-RLE compressed data. To use non-RLE-compressed
|
||||
data, set the global variable 'stbi_write_tga_with_rle' to 0.
|
||||
|
||||
JPEG does ignore alpha channels in input data; quality is between 1 and 100.
|
||||
Higher quality looks better but results in a bigger image.
|
||||
JPEG baseline (no JPEG progressive).
|
||||
|
||||
CREDITS:
|
||||
|
||||
|
@ -94,6 +100,9 @@ CREDITS:
|
|||
Alan Hickman
|
||||
initial file IO callback implementation
|
||||
Emmanuel Julien
|
||||
JPEG
|
||||
Jon Olick (original jo_jpeg.cpp code)
|
||||
Daniel Gibson
|
||||
bugfixes:
|
||||
github:Chribba
|
||||
Guillaume Chereau
|
||||
|
@ -131,6 +140,7 @@ STBIWDEF int stbi_write_png(char const *filename, int w, int h, int comp, const
|
|||
STBIWDEF int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data);
|
||||
STBIWDEF int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data);
|
||||
STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data);
|
||||
STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality);
|
||||
#endif
|
||||
|
||||
typedef void stbi_write_func(void *context, void *data, int size);
|
||||
|
@ -139,6 +149,7 @@ STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int w,
|
|||
STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data);
|
||||
STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data);
|
||||
STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data);
|
||||
STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -277,6 +288,11 @@ static void stbiw__writef(stbi__write_context *s, const char *fmt, ...)
|
|||
va_end(v);
|
||||
}
|
||||
|
||||
static void stbiw__putc(stbi__write_context *s, unsigned char c)
|
||||
{
|
||||
s->func(s->context, &c, 1);
|
||||
}
|
||||
|
||||
static void stbiw__write3(stbi__write_context *s, unsigned char a, unsigned char b, unsigned char c)
|
||||
{
|
||||
unsigned char arr[3];
|
||||
|
@ -450,7 +466,7 @@ static int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, v
|
|||
return 1;
|
||||
}
|
||||
|
||||
int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data)
|
||||
STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data)
|
||||
{
|
||||
stbi__write_context s;
|
||||
stbi__start_write_callbacks(&s, func, context);
|
||||
|
@ -458,7 +474,7 @@ int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, i
|
|||
}
|
||||
|
||||
#ifndef STBI_WRITE_NO_STDIO
|
||||
int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data)
|
||||
STBIWDEF int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data)
|
||||
{
|
||||
stbi__write_context s;
|
||||
if (stbi__start_write_file(&s,filename)) {
|
||||
|
@ -620,7 +636,7 @@ static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, f
|
|||
}
|
||||
}
|
||||
|
||||
int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const float *data)
|
||||
STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const float *data)
|
||||
{
|
||||
stbi__write_context s;
|
||||
stbi__start_write_callbacks(&s, func, context);
|
||||
|
@ -628,7 +644,7 @@ int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, i
|
|||
}
|
||||
|
||||
#ifndef STBI_WRITE_NO_STDIO
|
||||
int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data)
|
||||
STBIWDEF int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data)
|
||||
{
|
||||
stbi__write_context s;
|
||||
if (stbi__start_write_file(&s,filename)) {
|
||||
|
@ -1013,9 +1029,359 @@ STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int x,
|
|||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* ***************************************************************************
|
||||
*
|
||||
* JPEG writer
|
||||
*
|
||||
* This is based on Jon Olick's jo_jpeg.cpp:
|
||||
* public domain Simple, Minimalistic JPEG writer - http://www.jonolick.com/code.html
|
||||
*/
|
||||
|
||||
static const unsigned char stbiw__jpg_ZigZag[] = { 0,1,5,6,14,15,27,28,2,4,7,13,16,26,29,42,3,8,12,17,25,30,41,43,9,11,18,
|
||||
24,31,40,44,53,10,19,23,32,39,45,52,54,20,22,33,38,46,51,55,60,21,34,37,47,50,56,59,61,35,36,48,49,57,58,62,63 };
|
||||
|
||||
static void stbiw__jpg_writeBits(stbi__write_context *s, int *bitBufP, int *bitCntP, const unsigned short *bs) {
|
||||
int bitBuf = *bitBufP, bitCnt = *bitCntP;
|
||||
bitCnt += bs[1];
|
||||
bitBuf |= bs[0] << (24 - bitCnt);
|
||||
while(bitCnt >= 8) {
|
||||
unsigned char c = (bitBuf >> 16) & 255;
|
||||
stbiw__putc(s, c);
|
||||
if(c == 255) {
|
||||
stbiw__putc(s, 0);
|
||||
}
|
||||
bitBuf <<= 8;
|
||||
bitCnt -= 8;
|
||||
}
|
||||
*bitBufP = bitBuf;
|
||||
*bitCntP = bitCnt;
|
||||
}
|
||||
|
||||
static void stbiw__jpg_DCT(float *d0p, float *d1p, float *d2p, float *d3p, float *d4p, float *d5p, float *d6p, float *d7p) {
|
||||
float d0 = *d0p, d1 = *d1p, d2 = *d2p, d3 = *d3p, d4 = *d4p, d5 = *d5p, d6 = *d6p, d7 = *d7p;
|
||||
float z1, z2, z3, z4, z5, z11, z13;
|
||||
|
||||
float tmp0 = d0 + d7;
|
||||
float tmp7 = d0 - d7;
|
||||
float tmp1 = d1 + d6;
|
||||
float tmp6 = d1 - d6;
|
||||
float tmp2 = d2 + d5;
|
||||
float tmp5 = d2 - d5;
|
||||
float tmp3 = d3 + d4;
|
||||
float tmp4 = d3 - d4;
|
||||
|
||||
// Even part
|
||||
float tmp10 = tmp0 + tmp3; // phase 2
|
||||
float tmp13 = tmp0 - tmp3;
|
||||
float tmp11 = tmp1 + tmp2;
|
||||
float tmp12 = tmp1 - tmp2;
|
||||
|
||||
d0 = tmp10 + tmp11; // phase 3
|
||||
d4 = tmp10 - tmp11;
|
||||
|
||||
z1 = (tmp12 + tmp13) * 0.707106781f; // c4
|
||||
d2 = tmp13 + z1; // phase 5
|
||||
d6 = tmp13 - z1;
|
||||
|
||||
// Odd part
|
||||
tmp10 = tmp4 + tmp5; // phase 2
|
||||
tmp11 = tmp5 + tmp6;
|
||||
tmp12 = tmp6 + tmp7;
|
||||
|
||||
// The rotator is modified from fig 4-8 to avoid extra negations.
|
||||
z5 = (tmp10 - tmp12) * 0.382683433f; // c6
|
||||
z2 = tmp10 * 0.541196100f + z5; // c2-c6
|
||||
z4 = tmp12 * 1.306562965f + z5; // c2+c6
|
||||
z3 = tmp11 * 0.707106781f; // c4
|
||||
|
||||
z11 = tmp7 + z3; // phase 5
|
||||
z13 = tmp7 - z3;
|
||||
|
||||
*d5p = z13 + z2; // phase 6
|
||||
*d3p = z13 - z2;
|
||||
*d1p = z11 + z4;
|
||||
*d7p = z11 - z4;
|
||||
|
||||
*d0p = d0; *d2p = d2; *d4p = d4; *d6p = d6;
|
||||
}
|
||||
|
||||
static void stbiw__jpg_calcBits(int val, unsigned short bits[2]) {
|
||||
int tmp1 = val < 0 ? -val : val;
|
||||
val = val < 0 ? val-1 : val;
|
||||
bits[1] = 1;
|
||||
while(tmp1 >>= 1) {
|
||||
++bits[1];
|
||||
}
|
||||
bits[0] = val & ((1<<bits[1])-1);
|
||||
}
|
||||
|
||||
static int stbiw__jpg_processDU(stbi__write_context *s, int *bitBuf, int *bitCnt, float *CDU, float *fdtbl, int DC, const unsigned short HTDC[256][2], const unsigned short HTAC[256][2]) {
|
||||
const unsigned short EOB[2] = { HTAC[0x00][0], HTAC[0x00][1] };
|
||||
const unsigned short M16zeroes[2] = { HTAC[0xF0][0], HTAC[0xF0][1] };
|
||||
int dataOff, i, diff, end0pos;
|
||||
int DU[64];
|
||||
|
||||
// DCT rows
|
||||
for(dataOff=0; dataOff<64; dataOff+=8) {
|
||||
stbiw__jpg_DCT(&CDU[dataOff], &CDU[dataOff+1], &CDU[dataOff+2], &CDU[dataOff+3], &CDU[dataOff+4], &CDU[dataOff+5], &CDU[dataOff+6], &CDU[dataOff+7]);
|
||||
}
|
||||
// DCT columns
|
||||
for(dataOff=0; dataOff<8; ++dataOff) {
|
||||
stbiw__jpg_DCT(&CDU[dataOff], &CDU[dataOff+8], &CDU[dataOff+16], &CDU[dataOff+24], &CDU[dataOff+32], &CDU[dataOff+40], &CDU[dataOff+48], &CDU[dataOff+56]);
|
||||
}
|
||||
// Quantize/descale/zigzag the coefficients
|
||||
for(i=0; i<64; ++i) {
|
||||
float v = CDU[i]*fdtbl[i];
|
||||
// DU[stbiw__jpg_ZigZag[i]] = (int)(v < 0 ? ceilf(v - 0.5f) : floorf(v + 0.5f));
|
||||
// ceilf() and floorf() are C99, not C89, but I /think/ they're not needed here anyway?
|
||||
DU[stbiw__jpg_ZigZag[i]] = (int)(v < 0 ? v - 0.5f : v + 0.5f);
|
||||
}
|
||||
|
||||
// Encode DC
|
||||
diff = DU[0] - DC;
|
||||
if (diff == 0) {
|
||||
stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTDC[0]);
|
||||
} else {
|
||||
unsigned short bits[2];
|
||||
stbiw__jpg_calcBits(diff, bits);
|
||||
stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTDC[bits[1]]);
|
||||
stbiw__jpg_writeBits(s, bitBuf, bitCnt, bits);
|
||||
}
|
||||
// Encode ACs
|
||||
end0pos = 63;
|
||||
for(; (end0pos>0)&&(DU[end0pos]==0); --end0pos) {
|
||||
}
|
||||
// end0pos = first element in reverse order !=0
|
||||
if(end0pos == 0) {
|
||||
stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB);
|
||||
return DU[0];
|
||||
}
|
||||
for(i = 1; i <= end0pos; ++i) {
|
||||
int startpos = i;
|
||||
int nrzeroes;
|
||||
unsigned short bits[2];
|
||||
for (; DU[i]==0 && i<=end0pos; ++i) {
|
||||
}
|
||||
nrzeroes = i-startpos;
|
||||
if ( nrzeroes >= 16 ) {
|
||||
int lng = nrzeroes>>4;
|
||||
int nrmarker;
|
||||
for (nrmarker=1; nrmarker <= lng; ++nrmarker)
|
||||
stbiw__jpg_writeBits(s, bitBuf, bitCnt, M16zeroes);
|
||||
nrzeroes &= 15;
|
||||
}
|
||||
stbiw__jpg_calcBits(DU[i], bits);
|
||||
stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTAC[(nrzeroes<<4)+bits[1]]);
|
||||
stbiw__jpg_writeBits(s, bitBuf, bitCnt, bits);
|
||||
}
|
||||
if(end0pos != 63) {
|
||||
stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB);
|
||||
}
|
||||
return DU[0];
|
||||
}
|
||||
|
||||
static int stbi_write_jpg_core(stbi__write_context *s, int width, int height, int comp, const void* data, int quality) {
|
||||
// Constants that don't pollute global namespace
|
||||
static const unsigned char std_dc_luminance_nrcodes[] = {0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0};
|
||||
static const unsigned char std_dc_luminance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11};
|
||||
static const unsigned char std_ac_luminance_nrcodes[] = {0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d};
|
||||
static const unsigned char std_ac_luminance_values[] = {
|
||||
0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08,
|
||||
0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0,0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28,
|
||||
0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,
|
||||
0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89,
|
||||
0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,
|
||||
0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2,
|
||||
0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa
|
||||
};
|
||||
static const unsigned char std_dc_chrominance_nrcodes[] = {0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0};
|
||||
static const unsigned char std_dc_chrominance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11};
|
||||
static const unsigned char std_ac_chrominance_nrcodes[] = {0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77};
|
||||
static const unsigned char std_ac_chrominance_values[] = {
|
||||
0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,
|
||||
0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0,0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26,
|
||||
0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,
|
||||
0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87,
|
||||
0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,
|
||||
0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,
|
||||
0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa
|
||||
};
|
||||
// Huffman tables
|
||||
static const unsigned short YDC_HT[256][2] = { {0,2},{2,3},{3,3},{4,3},{5,3},{6,3},{14,4},{30,5},{62,6},{126,7},{254,8},{510,9}};
|
||||
static const unsigned short UVDC_HT[256][2] = { {0,2},{1,2},{2,2},{6,3},{14,4},{30,5},{62,6},{126,7},{254,8},{510,9},{1022,10},{2046,11}};
|
||||
static const unsigned short YAC_HT[256][2] = {
|
||||
{10,4},{0,2},{1,2},{4,3},{11,4},{26,5},{120,7},{248,8},{1014,10},{65410,16},{65411,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
|
||||
{12,4},{27,5},{121,7},{502,9},{2038,11},{65412,16},{65413,16},{65414,16},{65415,16},{65416,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
|
||||
{28,5},{249,8},{1015,10},{4084,12},{65417,16},{65418,16},{65419,16},{65420,16},{65421,16},{65422,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
|
||||
{58,6},{503,9},{4085,12},{65423,16},{65424,16},{65425,16},{65426,16},{65427,16},{65428,16},{65429,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
|
||||
{59,6},{1016,10},{65430,16},{65431,16},{65432,16},{65433,16},{65434,16},{65435,16},{65436,16},{65437,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
|
||||
{122,7},{2039,11},{65438,16},{65439,16},{65440,16},{65441,16},{65442,16},{65443,16},{65444,16},{65445,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
|
||||
{123,7},{4086,12},{65446,16},{65447,16},{65448,16},{65449,16},{65450,16},{65451,16},{65452,16},{65453,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
|
||||
{250,8},{4087,12},{65454,16},{65455,16},{65456,16},{65457,16},{65458,16},{65459,16},{65460,16},{65461,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
|
||||
{504,9},{32704,15},{65462,16},{65463,16},{65464,16},{65465,16},{65466,16},{65467,16},{65468,16},{65469,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
|
||||
{505,9},{65470,16},{65471,16},{65472,16},{65473,16},{65474,16},{65475,16},{65476,16},{65477,16},{65478,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
|
||||
{506,9},{65479,16},{65480,16},{65481,16},{65482,16},{65483,16},{65484,16},{65485,16},{65486,16},{65487,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
|
||||
{1017,10},{65488,16},{65489,16},{65490,16},{65491,16},{65492,16},{65493,16},{65494,16},{65495,16},{65496,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
|
||||
{1018,10},{65497,16},{65498,16},{65499,16},{65500,16},{65501,16},{65502,16},{65503,16},{65504,16},{65505,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
|
||||
{2040,11},{65506,16},{65507,16},{65508,16},{65509,16},{65510,16},{65511,16},{65512,16},{65513,16},{65514,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
|
||||
{65515,16},{65516,16},{65517,16},{65518,16},{65519,16},{65520,16},{65521,16},{65522,16},{65523,16},{65524,16},{0,0},{0,0},{0,0},{0,0},{0,0},
|
||||
{2041,11},{65525,16},{65526,16},{65527,16},{65528,16},{65529,16},{65530,16},{65531,16},{65532,16},{65533,16},{65534,16},{0,0},{0,0},{0,0},{0,0},{0,0}
|
||||
};
|
||||
static const unsigned short UVAC_HT[256][2] = {
|
||||
{0,2},{1,2},{4,3},{10,4},{24,5},{25,5},{56,6},{120,7},{500,9},{1014,10},{4084,12},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
|
||||
{11,4},{57,6},{246,8},{501,9},{2038,11},{4085,12},{65416,16},{65417,16},{65418,16},{65419,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
|
||||
{26,5},{247,8},{1015,10},{4086,12},{32706,15},{65420,16},{65421,16},{65422,16},{65423,16},{65424,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
|
||||
{27,5},{248,8},{1016,10},{4087,12},{65425,16},{65426,16},{65427,16},{65428,16},{65429,16},{65430,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
|
||||
{58,6},{502,9},{65431,16},{65432,16},{65433,16},{65434,16},{65435,16},{65436,16},{65437,16},{65438,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
|
||||
{59,6},{1017,10},{65439,16},{65440,16},{65441,16},{65442,16},{65443,16},{65444,16},{65445,16},{65446,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
|
||||
{121,7},{2039,11},{65447,16},{65448,16},{65449,16},{65450,16},{65451,16},{65452,16},{65453,16},{65454,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
|
||||
{122,7},{2040,11},{65455,16},{65456,16},{65457,16},{65458,16},{65459,16},{65460,16},{65461,16},{65462,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
|
||||
{249,8},{65463,16},{65464,16},{65465,16},{65466,16},{65467,16},{65468,16},{65469,16},{65470,16},{65471,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
|
||||
{503,9},{65472,16},{65473,16},{65474,16},{65475,16},{65476,16},{65477,16},{65478,16},{65479,16},{65480,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
|
||||
{504,9},{65481,16},{65482,16},{65483,16},{65484,16},{65485,16},{65486,16},{65487,16},{65488,16},{65489,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
|
||||
{505,9},{65490,16},{65491,16},{65492,16},{65493,16},{65494,16},{65495,16},{65496,16},{65497,16},{65498,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
|
||||
{506,9},{65499,16},{65500,16},{65501,16},{65502,16},{65503,16},{65504,16},{65505,16},{65506,16},{65507,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
|
||||
{2041,11},{65508,16},{65509,16},{65510,16},{65511,16},{65512,16},{65513,16},{65514,16},{65515,16},{65516,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
|
||||
{16352,14},{65517,16},{65518,16},{65519,16},{65520,16},{65521,16},{65522,16},{65523,16},{65524,16},{65525,16},{0,0},{0,0},{0,0},{0,0},{0,0},
|
||||
{1018,10},{32707,15},{65526,16},{65527,16},{65528,16},{65529,16},{65530,16},{65531,16},{65532,16},{65533,16},{65534,16},{0,0},{0,0},{0,0},{0,0},{0,0}
|
||||
};
|
||||
static const int YQT[] = {16,11,10,16,24,40,51,61,12,12,14,19,26,58,60,55,14,13,16,24,40,57,69,56,14,17,22,29,51,87,80,62,18,22,
|
||||
37,56,68,109,103,77,24,35,55,64,81,104,113,92,49,64,78,87,103,121,120,101,72,92,95,98,112,100,103,99};
|
||||
static const int UVQT[] = {17,18,24,47,99,99,99,99,18,21,26,66,99,99,99,99,24,26,56,99,99,99,99,99,47,66,99,99,99,99,99,99,
|
||||
99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99};
|
||||
static const float aasf[] = { 1.0f * 2.828427125f, 1.387039845f * 2.828427125f, 1.306562965f * 2.828427125f, 1.175875602f * 2.828427125f,
|
||||
1.0f * 2.828427125f, 0.785694958f * 2.828427125f, 0.541196100f * 2.828427125f, 0.275899379f * 2.828427125f };
|
||||
|
||||
int row, col, i, k;
|
||||
float fdtbl_Y[64], fdtbl_UV[64];
|
||||
unsigned char YTable[64], UVTable[64];
|
||||
|
||||
if(!data || !width || !height || comp > 4 || comp < 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
quality = quality ? quality : 90;
|
||||
quality = quality < 1 ? 1 : quality > 100 ? 100 : quality;
|
||||
quality = quality < 50 ? 5000 / quality : 200 - quality * 2;
|
||||
|
||||
for(i = 0; i < 64; ++i) {
|
||||
int uvti, yti = (YQT[i]*quality+50)/100;
|
||||
YTable[stbiw__jpg_ZigZag[i]] = (unsigned char) (yti < 1 ? 1 : yti > 255 ? 255 : yti);
|
||||
uvti = (UVQT[i]*quality+50)/100;
|
||||
UVTable[stbiw__jpg_ZigZag[i]] = (unsigned char) (uvti < 1 ? 1 : uvti > 255 ? 255 : uvti);
|
||||
}
|
||||
|
||||
for(row = 0, k = 0; row < 8; ++row) {
|
||||
for(col = 0; col < 8; ++col, ++k) {
|
||||
fdtbl_Y[k] = 1 / (YTable [stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]);
|
||||
fdtbl_UV[k] = 1 / (UVTable[stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]);
|
||||
}
|
||||
}
|
||||
|
||||
// Write Headers
|
||||
{
|
||||
static const unsigned char head0[] = { 0xFF,0xD8,0xFF,0xE0,0,0x10,'J','F','I','F',0,1,1,0,0,1,0,1,0,0,0xFF,0xDB,0,0x84,0 };
|
||||
static const unsigned char head2[] = { 0xFF,0xDA,0,0xC,3,1,0,2,0x11,3,0x11,0,0x3F,0 };
|
||||
const unsigned char head1[] = { 0xFF,0xC0,0,0x11,8,(unsigned char)(height>>8),STBIW_UCHAR(height),(unsigned char)(width>>8),STBIW_UCHAR(width),
|
||||
3,1,0x11,0,2,0x11,1,3,0x11,1,0xFF,0xC4,0x01,0xA2,0 };
|
||||
s->func(s->context, (void*)head0, sizeof(head0));
|
||||
s->func(s->context, (void*)YTable, sizeof(YTable));
|
||||
stbiw__putc(s, 1);
|
||||
s->func(s->context, UVTable, sizeof(UVTable));
|
||||
s->func(s->context, (void*)head1, sizeof(head1));
|
||||
s->func(s->context, (void*)(std_dc_luminance_nrcodes+1), sizeof(std_dc_luminance_nrcodes)-1);
|
||||
s->func(s->context, (void*)std_dc_luminance_values, sizeof(std_dc_luminance_values));
|
||||
stbiw__putc(s, 0x10); // HTYACinfo
|
||||
s->func(s->context, (void*)(std_ac_luminance_nrcodes+1), sizeof(std_ac_luminance_nrcodes)-1);
|
||||
s->func(s->context, (void*)std_ac_luminance_values, sizeof(std_ac_luminance_values));
|
||||
stbiw__putc(s, 1); // HTUDCinfo
|
||||
s->func(s->context, (void*)(std_dc_chrominance_nrcodes+1), sizeof(std_dc_chrominance_nrcodes)-1);
|
||||
s->func(s->context, (void*)std_dc_chrominance_values, sizeof(std_dc_chrominance_values));
|
||||
stbiw__putc(s, 0x11); // HTUACinfo
|
||||
s->func(s->context, (void*)(std_ac_chrominance_nrcodes+1), sizeof(std_ac_chrominance_nrcodes)-1);
|
||||
s->func(s->context, (void*)std_ac_chrominance_values, sizeof(std_ac_chrominance_values));
|
||||
s->func(s->context, (void*)head2, sizeof(head2));
|
||||
}
|
||||
|
||||
// Encode 8x8 macroblocks
|
||||
{
|
||||
static const unsigned short fillBits[] = {0x7F, 7};
|
||||
const unsigned char *imageData = (const unsigned char *)data;
|
||||
int DCY=0, DCU=0, DCV=0;
|
||||
int bitBuf=0, bitCnt=0;
|
||||
// comp == 2 is grey+alpha (alpha is ignored)
|
||||
int ofsG = comp > 2 ? 1 : 0, ofsB = comp > 2 ? 2 : 0;
|
||||
int x, y, pos;
|
||||
for(y = 0; y < height; y += 8) {
|
||||
for(x = 0; x < width; x += 8) {
|
||||
float YDU[64], UDU[64], VDU[64];
|
||||
for(row = y, pos = 0; row < y+8; ++row) {
|
||||
for(col = x; col < x+8; ++col, ++pos) {
|
||||
int p = row*width*comp + col*comp;
|
||||
float r, g, b;
|
||||
if(row >= height) {
|
||||
p -= width*comp*(row+1 - height);
|
||||
}
|
||||
if(col >= width) {
|
||||
p -= comp*(col+1 - width);
|
||||
}
|
||||
|
||||
r = imageData[p+0];
|
||||
g = imageData[p+ofsG];
|
||||
b = imageData[p+ofsB];
|
||||
YDU[pos]=+0.29900f*r+0.58700f*g+0.11400f*b-128;
|
||||
UDU[pos]=-0.16874f*r-0.33126f*g+0.50000f*b;
|
||||
VDU[pos]=+0.50000f*r-0.41869f*g-0.08131f*b;
|
||||
}
|
||||
}
|
||||
|
||||
DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, YDU, fdtbl_Y, DCY, YDC_HT, YAC_HT);
|
||||
DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, UDU, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);
|
||||
DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, VDU, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);
|
||||
}
|
||||
}
|
||||
|
||||
// Do the bit alignment of the EOI marker
|
||||
stbiw__jpg_writeBits(s, &bitBuf, &bitCnt, fillBits);
|
||||
}
|
||||
|
||||
// EOI
|
||||
stbiw__putc(s, 0xFF);
|
||||
stbiw__putc(s, 0xD9);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality)
|
||||
{
|
||||
stbi__write_context s;
|
||||
stbi__start_write_callbacks(&s, func, context);
|
||||
return stbi_write_jpg_core(&s, x, y, comp, (void *) data, quality);
|
||||
}
|
||||
|
||||
|
||||
#ifndef STBI_WRITE_NO_STDIO
|
||||
STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality)
|
||||
{
|
||||
stbi__write_context s;
|
||||
if (stbi__start_write_file(&s,filename)) {
|
||||
int r = stbi_write_jpg_core(&s, x, y, comp, data, quality);
|
||||
stbi__end_write_file(&s);
|
||||
return r;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
|
||||
/* Revision history
|
||||
1.07 (2017-07-24)
|
||||
doc fix
|
||||
1.06 (2017-07-23)
|
||||
writing JPEG (using Jon Olick's code)
|
||||
1.05 ???
|
||||
1.04 (2017-03-03)
|
||||
monochrome BMP expansion
|
||||
1.03 ???
|
||||
|
|
316
raylib/external/stb_perlin.h
vendored
Normal file
316
raylib/external/stb_perlin.h
vendored
Normal file
|
@ -0,0 +1,316 @@
|
|||
// stb_perlin.h - v0.3 - perlin noise
|
||||
// public domain single-file C implementation by Sean Barrett
|
||||
//
|
||||
// LICENSE
|
||||
//
|
||||
// See end of file.
|
||||
//
|
||||
//
|
||||
// to create the implementation,
|
||||
// #define STB_PERLIN_IMPLEMENTATION
|
||||
// in *one* C/CPP file that includes this file.
|
||||
//
|
||||
//
|
||||
// Documentation:
|
||||
//
|
||||
// float stb_perlin_noise3( float x,
|
||||
// float y,
|
||||
// float z,
|
||||
// int x_wrap=0,
|
||||
// int y_wrap=0,
|
||||
// int z_wrap=0)
|
||||
//
|
||||
// This function computes a random value at the coordinate (x,y,z).
|
||||
// Adjacent random values are continuous but the noise fluctuates
|
||||
// its randomness with period 1, i.e. takes on wholly unrelated values
|
||||
// at integer points. Specifically, this implements Ken Perlin's
|
||||
// revised noise function from 2002.
|
||||
//
|
||||
// The "wrap" parameters can be used to create wraparound noise that
|
||||
// wraps at powers of two. The numbers MUST be powers of two. Specify
|
||||
// 0 to mean "don't care". (The noise always wraps every 256 due
|
||||
// details of the implementation, even if you ask for larger or no
|
||||
// wrapping.)
|
||||
//
|
||||
// Fractal Noise:
|
||||
//
|
||||
// Three common fractal noise functions are included, which produce
|
||||
// a wide variety of nice effects depending on the parameters
|
||||
// provided. Note that each function will call stb_perlin_noise3
|
||||
// 'octaves' times, so this parameter will affect runtime.
|
||||
//
|
||||
// float stb_perlin_ridge_noise3(float x, float y, float z,
|
||||
// float lacunarity, float gain, float offset, int octaves,
|
||||
// int x_wrap, int y_wrap, int z_wrap);
|
||||
//
|
||||
// float stb_perlin_fbm_noise3(float x, float y, float z,
|
||||
// float lacunarity, float gain, int octaves,
|
||||
// int x_wrap, int y_wrap, int z_wrap);
|
||||
//
|
||||
// float stb_perlin_turbulence_noise3(float x, float y, float z,
|
||||
// float lacunarity, float gain,int octaves,
|
||||
// int x_wrap, int y_wrap, int z_wrap);
|
||||
//
|
||||
// Typical values to start playing with:
|
||||
// octaves = 6 -- number of "octaves" of noise3() to sum
|
||||
// lacunarity = ~ 2.0 -- spacing between successive octaves (use exactly 2.0 for wrapping output)
|
||||
// gain = 0.5 -- relative weighting applied to each successive octave
|
||||
// offset = 1.0? -- used to invert the ridges, may need to be larger, not sure
|
||||
//
|
||||
//
|
||||
// Contributors:
|
||||
// Jack Mott - additional noise functions
|
||||
//
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
extern float stb_perlin_noise3(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap);
|
||||
extern float stb_perlin_ridge_noise3(float x, float y, float z,float lacunarity, float gain, float offset, int octaves,int x_wrap, int y_wrap, int z_wrap);
|
||||
extern float stb_perlin_fbm_noise3(float x, float y, float z,float lacunarity, float gain, int octaves,int x_wrap, int y_wrap, int z_wrap);
|
||||
extern float stb_perlin_turbulence_noise3(float x, float y, float z, float lacunarity, float gain, int octaves,int x_wrap, int y_wrap, int z_wrap);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef STB_PERLIN_IMPLEMENTATION
|
||||
|
||||
// not same permutation table as Perlin's reference to avoid copyright issues;
|
||||
// Perlin's table can be found at http://mrl.nyu.edu/~perlin/noise/
|
||||
// @OPTIMIZE: should this be unsigned char instead of int for cache?
|
||||
static unsigned char stb__perlin_randtab[512] =
|
||||
{
|
||||
23, 125, 161, 52, 103, 117, 70, 37, 247, 101, 203, 169, 124, 126, 44, 123,
|
||||
152, 238, 145, 45, 171, 114, 253, 10, 192, 136, 4, 157, 249, 30, 35, 72,
|
||||
175, 63, 77, 90, 181, 16, 96, 111, 133, 104, 75, 162, 93, 56, 66, 240,
|
||||
8, 50, 84, 229, 49, 210, 173, 239, 141, 1, 87, 18, 2, 198, 143, 57,
|
||||
225, 160, 58, 217, 168, 206, 245, 204, 199, 6, 73, 60, 20, 230, 211, 233,
|
||||
94, 200, 88, 9, 74, 155, 33, 15, 219, 130, 226, 202, 83, 236, 42, 172,
|
||||
165, 218, 55, 222, 46, 107, 98, 154, 109, 67, 196, 178, 127, 158, 13, 243,
|
||||
65, 79, 166, 248, 25, 224, 115, 80, 68, 51, 184, 128, 232, 208, 151, 122,
|
||||
26, 212, 105, 43, 179, 213, 235, 148, 146, 89, 14, 195, 28, 78, 112, 76,
|
||||
250, 47, 24, 251, 140, 108, 186, 190, 228, 170, 183, 139, 39, 188, 244, 246,
|
||||
132, 48, 119, 144, 180, 138, 134, 193, 82, 182, 120, 121, 86, 220, 209, 3,
|
||||
91, 241, 149, 85, 205, 150, 113, 216, 31, 100, 41, 164, 177, 214, 153, 231,
|
||||
38, 71, 185, 174, 97, 201, 29, 95, 7, 92, 54, 254, 191, 118, 34, 221,
|
||||
131, 11, 163, 99, 234, 81, 227, 147, 156, 176, 17, 142, 69, 12, 110, 62,
|
||||
27, 255, 0, 194, 59, 116, 242, 252, 19, 21, 187, 53, 207, 129, 64, 135,
|
||||
61, 40, 167, 237, 102, 223, 106, 159, 197, 189, 215, 137, 36, 32, 22, 5,
|
||||
|
||||
// and a second copy so we don't need an extra mask or static initializer
|
||||
23, 125, 161, 52, 103, 117, 70, 37, 247, 101, 203, 169, 124, 126, 44, 123,
|
||||
152, 238, 145, 45, 171, 114, 253, 10, 192, 136, 4, 157, 249, 30, 35, 72,
|
||||
175, 63, 77, 90, 181, 16, 96, 111, 133, 104, 75, 162, 93, 56, 66, 240,
|
||||
8, 50, 84, 229, 49, 210, 173, 239, 141, 1, 87, 18, 2, 198, 143, 57,
|
||||
225, 160, 58, 217, 168, 206, 245, 204, 199, 6, 73, 60, 20, 230, 211, 233,
|
||||
94, 200, 88, 9, 74, 155, 33, 15, 219, 130, 226, 202, 83, 236, 42, 172,
|
||||
165, 218, 55, 222, 46, 107, 98, 154, 109, 67, 196, 178, 127, 158, 13, 243,
|
||||
65, 79, 166, 248, 25, 224, 115, 80, 68, 51, 184, 128, 232, 208, 151, 122,
|
||||
26, 212, 105, 43, 179, 213, 235, 148, 146, 89, 14, 195, 28, 78, 112, 76,
|
||||
250, 47, 24, 251, 140, 108, 186, 190, 228, 170, 183, 139, 39, 188, 244, 246,
|
||||
132, 48, 119, 144, 180, 138, 134, 193, 82, 182, 120, 121, 86, 220, 209, 3,
|
||||
91, 241, 149, 85, 205, 150, 113, 216, 31, 100, 41, 164, 177, 214, 153, 231,
|
||||
38, 71, 185, 174, 97, 201, 29, 95, 7, 92, 54, 254, 191, 118, 34, 221,
|
||||
131, 11, 163, 99, 234, 81, 227, 147, 156, 176, 17, 142, 69, 12, 110, 62,
|
||||
27, 255, 0, 194, 59, 116, 242, 252, 19, 21, 187, 53, 207, 129, 64, 135,
|
||||
61, 40, 167, 237, 102, 223, 106, 159, 197, 189, 215, 137, 36, 32, 22, 5,
|
||||
};
|
||||
|
||||
static float stb__perlin_lerp(float a, float b, float t)
|
||||
{
|
||||
return a + (b-a) * t;
|
||||
}
|
||||
|
||||
static int stb__perlin_fastfloor(float a)
|
||||
{
|
||||
int ai = (int) a;
|
||||
return (a < ai) ? ai-1 : ai;
|
||||
}
|
||||
|
||||
// different grad function from Perlin's, but easy to modify to match reference
|
||||
static float stb__perlin_grad(int hash, float x, float y, float z)
|
||||
{
|
||||
static float basis[12][4] =
|
||||
{
|
||||
{ 1, 1, 0 },
|
||||
{ -1, 1, 0 },
|
||||
{ 1,-1, 0 },
|
||||
{ -1,-1, 0 },
|
||||
{ 1, 0, 1 },
|
||||
{ -1, 0, 1 },
|
||||
{ 1, 0,-1 },
|
||||
{ -1, 0,-1 },
|
||||
{ 0, 1, 1 },
|
||||
{ 0,-1, 1 },
|
||||
{ 0, 1,-1 },
|
||||
{ 0,-1,-1 },
|
||||
};
|
||||
|
||||
// perlin's gradient has 12 cases so some get used 1/16th of the time
|
||||
// and some 2/16ths. We reduce bias by changing those fractions
|
||||
// to 5/64ths and 6/64ths, and the same 4 cases get the extra weight.
|
||||
static unsigned char indices[64] =
|
||||
{
|
||||
0,1,2,3,4,5,6,7,8,9,10,11,
|
||||
0,9,1,11,
|
||||
0,1,2,3,4,5,6,7,8,9,10,11,
|
||||
0,1,2,3,4,5,6,7,8,9,10,11,
|
||||
0,1,2,3,4,5,6,7,8,9,10,11,
|
||||
0,1,2,3,4,5,6,7,8,9,10,11,
|
||||
};
|
||||
|
||||
// if you use reference permutation table, change 63 below to 15 to match reference
|
||||
// (this is why the ordering of the table above is funky)
|
||||
float *grad = basis[indices[hash & 63]];
|
||||
return grad[0]*x + grad[1]*y + grad[2]*z;
|
||||
}
|
||||
|
||||
float stb_perlin_noise3(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap)
|
||||
{
|
||||
float u,v,w;
|
||||
float n000,n001,n010,n011,n100,n101,n110,n111;
|
||||
float n00,n01,n10,n11;
|
||||
float n0,n1;
|
||||
|
||||
unsigned int x_mask = (x_wrap-1) & 255;
|
||||
unsigned int y_mask = (y_wrap-1) & 255;
|
||||
unsigned int z_mask = (z_wrap-1) & 255;
|
||||
int px = stb__perlin_fastfloor(x);
|
||||
int py = stb__perlin_fastfloor(y);
|
||||
int pz = stb__perlin_fastfloor(z);
|
||||
int x0 = px & x_mask, x1 = (px+1) & x_mask;
|
||||
int y0 = py & y_mask, y1 = (py+1) & y_mask;
|
||||
int z0 = pz & z_mask, z1 = (pz+1) & z_mask;
|
||||
int r0,r1, r00,r01,r10,r11;
|
||||
|
||||
#define stb__perlin_ease(a) (((a*6-15)*a + 10) * a * a * a)
|
||||
|
||||
x -= px; u = stb__perlin_ease(x);
|
||||
y -= py; v = stb__perlin_ease(y);
|
||||
z -= pz; w = stb__perlin_ease(z);
|
||||
|
||||
r0 = stb__perlin_randtab[x0];
|
||||
r1 = stb__perlin_randtab[x1];
|
||||
|
||||
r00 = stb__perlin_randtab[r0+y0];
|
||||
r01 = stb__perlin_randtab[r0+y1];
|
||||
r10 = stb__perlin_randtab[r1+y0];
|
||||
r11 = stb__perlin_randtab[r1+y1];
|
||||
|
||||
n000 = stb__perlin_grad(stb__perlin_randtab[r00+z0], x , y , z );
|
||||
n001 = stb__perlin_grad(stb__perlin_randtab[r00+z1], x , y , z-1 );
|
||||
n010 = stb__perlin_grad(stb__perlin_randtab[r01+z0], x , y-1, z );
|
||||
n011 = stb__perlin_grad(stb__perlin_randtab[r01+z1], x , y-1, z-1 );
|
||||
n100 = stb__perlin_grad(stb__perlin_randtab[r10+z0], x-1, y , z );
|
||||
n101 = stb__perlin_grad(stb__perlin_randtab[r10+z1], x-1, y , z-1 );
|
||||
n110 = stb__perlin_grad(stb__perlin_randtab[r11+z0], x-1, y-1, z );
|
||||
n111 = stb__perlin_grad(stb__perlin_randtab[r11+z1], x-1, y-1, z-1 );
|
||||
|
||||
n00 = stb__perlin_lerp(n000,n001,w);
|
||||
n01 = stb__perlin_lerp(n010,n011,w);
|
||||
n10 = stb__perlin_lerp(n100,n101,w);
|
||||
n11 = stb__perlin_lerp(n110,n111,w);
|
||||
|
||||
n0 = stb__perlin_lerp(n00,n01,v);
|
||||
n1 = stb__perlin_lerp(n10,n11,v);
|
||||
|
||||
return stb__perlin_lerp(n0,n1,u);
|
||||
}
|
||||
|
||||
float stb_perlin_ridge_noise3(float x, float y, float z,float lacunarity, float gain, float offset, int octaves,int x_wrap, int y_wrap, int z_wrap)
|
||||
{
|
||||
int i;
|
||||
float frequency = 1.0f;
|
||||
float prev = 1.0f;
|
||||
float amplitude = 0.5f;
|
||||
float sum = 0.0f;
|
||||
|
||||
for (i = 0; i < octaves; i++) {
|
||||
float r = (float)(stb_perlin_noise3(x*frequency,y*frequency,z*frequency,x_wrap,y_wrap,z_wrap));
|
||||
r = r<0 ? -r : r; // fabs()
|
||||
r = offset - r;
|
||||
r = r*r;
|
||||
sum += r*amplitude*prev;
|
||||
prev = r;
|
||||
frequency *= lacunarity;
|
||||
amplitude *= gain;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
float stb_perlin_fbm_noise3(float x, float y, float z,float lacunarity, float gain, int octaves,int x_wrap, int y_wrap, int z_wrap)
|
||||
{
|
||||
int i;
|
||||
float frequency = 1.0f;
|
||||
float amplitude = 1.0f;
|
||||
float sum = 0.0f;
|
||||
|
||||
for (i = 0; i < octaves; i++) {
|
||||
sum += stb_perlin_noise3(x*frequency,y*frequency,z*frequency,x_wrap,y_wrap,z_wrap)*amplitude;
|
||||
frequency *= lacunarity;
|
||||
amplitude *= gain;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
float stb_perlin_turbulence_noise3(float x, float y, float z, float lacunarity, float gain, int octaves,int x_wrap, int y_wrap, int z_wrap)
|
||||
{
|
||||
int i;
|
||||
float frequency = 1.0f;
|
||||
float amplitude = 1.0f;
|
||||
float sum = 0.0f;
|
||||
|
||||
for (i = 0; i < octaves; i++) {
|
||||
float r = stb_perlin_noise3(x*frequency,y*frequency,z*frequency,x_wrap,y_wrap,z_wrap)*amplitude;
|
||||
r = r<0 ? -r : r; // fabs()
|
||||
sum += r;
|
||||
frequency *= lacunarity;
|
||||
amplitude *= gain;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
#endif // STB_PERLIN_IMPLEMENTATION
|
||||
|
||||
/*
|
||||
------------------------------------------------------------------------------
|
||||
This software is available under 2 licenses -- choose whichever you prefer.
|
||||
------------------------------------------------------------------------------
|
||||
ALTERNATIVE A - MIT License
|
||||
Copyright (c) 2017 Sean Barrett
|
||||
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 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 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
------------------------------------------------------------------------------
|
||||
ALTERNATIVE B - Public Domain (www.unlicense.org)
|
||||
This is free and unencumbered software released into the public domain.
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
|
||||
software, either in source code form or as a compiled binary, for any purpose,
|
||||
commercial or non-commercial, and by any means.
|
||||
In jurisdictions that recognize copyright laws, the author or authors of this
|
||||
software dedicate any and all copyright interest in the software to the public
|
||||
domain. We make this dedication for the benefit of the public at large and to
|
||||
the detriment of our heirs and successors. We intend this dedication to be an
|
||||
overt act of relinquishment in perpetuity of all present and future rights to
|
||||
this software under copyright law.
|
||||
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 THE
|
||||
AUTHORS 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.
|
||||
------------------------------------------------------------------------------
|
||||
*/
|
11
raylib/external/stb_rect_pack.h
vendored
11
raylib/external/stb_rect_pack.h
vendored
|
@ -524,17 +524,6 @@ static int rect_height_compare(const void *a, const void *b)
|
|||
return (p->w > q->w) ? -1 : (p->w < q->w);
|
||||
}
|
||||
|
||||
static int rect_width_compare(const void *a, const void *b)
|
||||
{
|
||||
const stbrp_rect *p = (const stbrp_rect *) a;
|
||||
const stbrp_rect *q = (const stbrp_rect *) b;
|
||||
if (p->w > q->w)
|
||||
return -1;
|
||||
if (p->w < q->w)
|
||||
return 1;
|
||||
return (p->h > q->h) ? -1 : (p->h < q->h);
|
||||
}
|
||||
|
||||
static int rect_original_order(const void *a, const void *b)
|
||||
{
|
||||
const stbrp_rect *p = (const stbrp_rect *) a;
|
||||
|
|
529
raylib/external/stb_truetype.h
vendored
529
raylib/external/stb_truetype.h
vendored
|
@ -1,4 +1,4 @@
|
|||
// stb_truetype.h - v1.15 - public domain
|
||||
// stb_truetype.h - v1.17 - public domain
|
||||
// authored from 2009-2016 by Sean Barrett / RAD Game Tools
|
||||
//
|
||||
// This library processes TrueType files:
|
||||
|
@ -6,6 +6,7 @@
|
|||
// extract glyph metrics
|
||||
// extract glyph shapes
|
||||
// render glyphs to one-channel bitmaps with antialiasing (box filter)
|
||||
// render glyphs to one-channel SDF bitmaps (signed-distance field/function)
|
||||
//
|
||||
// Todo:
|
||||
// non-MS cmaps
|
||||
|
@ -26,9 +27,10 @@
|
|||
// Ryan Gordon
|
||||
// Simon Glass
|
||||
// github:IntellectualKitty
|
||||
// Imanol Celaya
|
||||
//
|
||||
// Bug/warning reports/fixes:
|
||||
// "Zer" on mollyrocket (with fix)
|
||||
// "Zer" on mollyrocket
|
||||
// Cass Everitt
|
||||
// stoiko (Haemimont Games)
|
||||
// Brian Hook
|
||||
|
@ -51,9 +53,12 @@
|
|||
// Thomas Fields
|
||||
// Derek Vinyard
|
||||
// Cort Stratton
|
||||
// github:oyvindjam
|
||||
//
|
||||
// VERSION HISTORY
|
||||
//
|
||||
// 1.17 (2017-07-23) make more arguments const; doc fix
|
||||
// 1.16 (2017-07-12) SDF support
|
||||
// 1.15 (2017-03-03) make more arguments const
|
||||
// 1.14 (2017-01-16) num-fonts-in-TTC function
|
||||
// 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts
|
||||
|
@ -92,7 +97,7 @@
|
|||
// Improved 3D API (more shippable):
|
||||
// #include "stb_rect_pack.h" -- optional, but you really want it
|
||||
// stbtt_PackBegin()
|
||||
// stbtt_PackSetOversample() -- for improved quality on small fonts
|
||||
// stbtt_PackSetOversampling() -- for improved quality on small fonts
|
||||
// stbtt_PackFontRanges() -- pack and renders
|
||||
// stbtt_PackEnd()
|
||||
// stbtt_GetPackedQuad()
|
||||
|
@ -110,6 +115,7 @@
|
|||
// Character advance/positioning
|
||||
// stbtt_GetCodepointHMetrics()
|
||||
// stbtt_GetFontVMetrics()
|
||||
// stbtt_GetFontVMetricsOS2()
|
||||
// stbtt_GetCodepointKernAdvance()
|
||||
//
|
||||
// Starting with version 1.06, the rasterizer was replaced with a new,
|
||||
|
@ -407,6 +413,18 @@ int main(int arg, char **argv)
|
|||
#ifndef STBTT_sqrt
|
||||
#include <math.h>
|
||||
#define STBTT_sqrt(x) sqrt(x)
|
||||
#define STBTT_pow(x,y) pow(x,y)
|
||||
#endif
|
||||
|
||||
#ifndef STBTT_cos
|
||||
#include <math.h>
|
||||
#define STBTT_cos(x) cos(x)
|
||||
#define STBTT_acos(x) acos(x)
|
||||
#endif
|
||||
|
||||
#ifndef STBTT_fabs
|
||||
#include <math.h>
|
||||
#define STBTT_fabs(x) fabs(x)
|
||||
#endif
|
||||
|
||||
#ifndef STBTT_fabs
|
||||
|
@ -432,7 +450,7 @@ int main(int arg, char **argv)
|
|||
#endif
|
||||
|
||||
#ifndef STBTT_memcpy
|
||||
#include <memory.h>
|
||||
#include <string.h>
|
||||
#define STBTT_memcpy memcpy
|
||||
#define STBTT_memset memset
|
||||
#endif
|
||||
|
@ -548,7 +566,7 @@ STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc);
|
|||
|
||||
#define STBTT_POINT_SIZE(x) (-(x))
|
||||
|
||||
STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, float font_size,
|
||||
STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size,
|
||||
int first_unicode_char_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range);
|
||||
// Creates character bitmaps from the font_index'th font found in fontdata (use
|
||||
// font_index=0 if you don't know what that is). It creates num_chars_in_range
|
||||
|
@ -573,7 +591,7 @@ typedef struct
|
|||
unsigned char h_oversample, v_oversample; // don't set these, they're used internally
|
||||
} stbtt_pack_range;
|
||||
|
||||
STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges);
|
||||
STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges);
|
||||
// Creates character bitmaps from multiple ranges of characters stored in
|
||||
// ranges. This will usually create a better-packed bitmap than multiple
|
||||
// calls to stbtt_PackFontRange. Note that you can call this multiple
|
||||
|
@ -715,6 +733,12 @@ STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, in
|
|||
// these are expressed in unscaled coordinates, so you must multiply by
|
||||
// the scale factor for a given size
|
||||
|
||||
STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap);
|
||||
// analogous to GetFontVMetrics, but returns the "typographic" values from the OS/2
|
||||
// table (specific to MS/Windows TTF files).
|
||||
//
|
||||
// Returns 1 on success (table present), 0 on failure.
|
||||
|
||||
STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1);
|
||||
// the bounding box around all possible characters
|
||||
|
||||
|
@ -809,6 +833,10 @@ STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, uns
|
|||
// same as stbtt_MakeCodepointBitmap, but you can specify a subpixel
|
||||
// shift for the character
|
||||
|
||||
STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint);
|
||||
// same as stbtt_MakeCodepointBitmapSubpixel, but prefiltering
|
||||
// is performed (see stbtt_PackSetOversampling)
|
||||
|
||||
STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1);
|
||||
// get the bbox of the bitmap centered around the glyph origin; so the
|
||||
// bitmap width is ix1-ix0, height is iy1-iy0, and location to place
|
||||
|
@ -826,6 +854,7 @@ STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float
|
|||
STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff);
|
||||
STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph);
|
||||
STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph);
|
||||
STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int glyph);
|
||||
STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1);
|
||||
STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1);
|
||||
|
||||
|
@ -848,6 +877,64 @@ STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, // 1-channel bitmap
|
|||
int invert, // if non-zero, vertically flip shape
|
||||
void *userdata); // context for to STBTT_MALLOC
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Signed Distance Function (or Field) rendering
|
||||
|
||||
STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata);
|
||||
// frees the SDF bitmap allocated below
|
||||
|
||||
STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff);
|
||||
STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff);
|
||||
// These functions compute a discretized SDF field for a single character, suitable for storing
|
||||
// in a single-channel texture, sampling with bilinear filtering, and testing against
|
||||
// larger than some threshhold to produce scalable fonts.
|
||||
// info -- the font
|
||||
// scale -- controls the size of the resulting SDF bitmap, same as it would be creating a regular bitmap
|
||||
// glyph/codepoint -- the character to generate the SDF for
|
||||
// padding -- extra "pixels" around the character which are filled with the distance to the character (not 0),
|
||||
// which allows effects like bit outlines
|
||||
// onedge_value -- value 0-255 to test the SDF against to reconstruct the character (i.e. the isocontour of the character)
|
||||
// pixel_dist_scale -- what value the SDF should increase by when moving one SDF "pixel" away from the edge (on the 0..255 scale)
|
||||
// if positive, > onedge_value is inside; if negative, < onedge_value is inside
|
||||
// width,height -- output height & width of the SDF bitmap (including padding)
|
||||
// xoff,yoff -- output origin of the character
|
||||
// return value -- a 2D array of bytes 0..255, width*height in size
|
||||
//
|
||||
// pixel_dist_scale & onedge_value are a scale & bias that allows you to make
|
||||
// optimal use of the limited 0..255 for your application, trading off precision
|
||||
// and special effects. SDF values outside the range 0..255 are clamped to 0..255.
|
||||
//
|
||||
// Example:
|
||||
// scale = stbtt_ScaleForPixelHeight(22)
|
||||
// padding = 5
|
||||
// onedge_value = 180
|
||||
// pixel_dist_scale = 180/5.0 = 36.0
|
||||
//
|
||||
// This will create an SDF bitmap in which the character is about 22 pixels
|
||||
// high but the whole bitmap is about 22+5+5=32 pixels high. To produce a filled
|
||||
// shape, sample the SDF at each pixel and fill the pixel if the SDF value
|
||||
// is greater than or equal to 180/255. (You'll actually want to antialias,
|
||||
// which is beyond the scope of this example.) Additionally, you can compute
|
||||
// offset outlines (e.g. to stroke the character border inside & outside,
|
||||
// or only outside). For example, to fill outside the character up to 3 SDF
|
||||
// pixels, you would compare against (180-36.0*3)/255 = 72/255. The above
|
||||
// choice of variables maps a range from 5 pixels outside the shape to
|
||||
// 2 pixels inside the shape to 0..255; this is intended primarily for apply
|
||||
// outside effects only (the interior range is needed to allow proper
|
||||
// antialiasing of the font at *smaller* sizes)
|
||||
//
|
||||
// The function computes the SDF analytically at each SDF pixel, not by e.g.
|
||||
// building a higher-res bitmap and approximating it. In theory the quality
|
||||
// should be as high as possible for an SDF of this size & representation, but
|
||||
// unclear if this is true in practice (perhaps building a higher-res bitmap
|
||||
// and computing from that can allow drop-out prevention).
|
||||
//
|
||||
// The algorithm has not been optimized at all, so expect it to be slow
|
||||
// if computing lots of characters or very large sizes.
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Finding the right font...
|
||||
|
@ -2201,6 +2288,17 @@ STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, in
|
|||
if (lineGap) *lineGap = ttSHORT(info->data+info->hhea + 8);
|
||||
}
|
||||
|
||||
STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap)
|
||||
{
|
||||
int tab = stbtt__find_table(info->data, info->fontstart, "OS/2");
|
||||
if (!tab)
|
||||
return 0;
|
||||
if (typoAscent ) *typoAscent = ttSHORT(info->data+tab + 68);
|
||||
if (typoDescent) *typoDescent = ttSHORT(info->data+tab + 70);
|
||||
if (typoLineGap) *typoLineGap = ttSHORT(info->data+tab + 72);
|
||||
return 1;
|
||||
}
|
||||
|
||||
STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1)
|
||||
{
|
||||
*x0 = ttSHORT(info->data + info->head + 36);
|
||||
|
@ -2693,19 +2791,18 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill,
|
|||
// from the other y segment, and it might ignored as an empty segment. to avoid
|
||||
// that, we need to explicitly produce segments based on x positions.
|
||||
|
||||
// rename variables to clear pairs
|
||||
// rename variables to clearly-defined pairs
|
||||
float y0 = y_top;
|
||||
float x1 = (float) (x);
|
||||
float x2 = (float) (x+1);
|
||||
float x3 = xb;
|
||||
float y3 = y_bottom;
|
||||
float y1,y2;
|
||||
|
||||
// x = e->x + e->dx * (y-y_top)
|
||||
// (y-y_top) = (x - e->x) / e->dx
|
||||
// y = (x - e->x) / e->dx + y_top
|
||||
y1 = (x - x0) / dx + y_top;
|
||||
y2 = (x+1 - x0) / dx + y_top;
|
||||
float y1 = (x - x0) / dx + y_top;
|
||||
float y2 = (x+1 - x0) / dx + y_top;
|
||||
|
||||
if (x0 < x1 && x3 > x2) { // three segments descending down-right
|
||||
stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1);
|
||||
|
@ -3600,6 +3697,29 @@ STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stb
|
|||
return k;
|
||||
}
|
||||
|
||||
STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int prefilter_x, int prefilter_y, float *sub_x, float *sub_y, int glyph)
|
||||
{
|
||||
stbtt_MakeGlyphBitmapSubpixel(info,
|
||||
output,
|
||||
out_w - (prefilter_x - 1),
|
||||
out_h - (prefilter_y - 1),
|
||||
out_stride,
|
||||
scale_x,
|
||||
scale_y,
|
||||
shift_x,
|
||||
shift_y,
|
||||
glyph);
|
||||
|
||||
if (prefilter_x > 1)
|
||||
stbtt__h_prefilter(output, out_w, out_h, out_stride, prefilter_x);
|
||||
|
||||
if (prefilter_y > 1)
|
||||
stbtt__v_prefilter(output, out_w, out_h, out_stride, prefilter_y);
|
||||
|
||||
*sub_x = stbtt__oversample_shift(prefilter_x);
|
||||
*sub_y = stbtt__oversample_shift(prefilter_y);
|
||||
}
|
||||
|
||||
// rects array must be big enough to accommodate all characters in the given ranges
|
||||
STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
|
||||
{
|
||||
|
@ -3688,7 +3808,7 @@ STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect
|
|||
stbrp_pack_rects((stbrp_context *) spc->pack_info, rects, num_rects);
|
||||
}
|
||||
|
||||
STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges)
|
||||
STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges)
|
||||
{
|
||||
stbtt_fontinfo info;
|
||||
int i,j,n, return_value = 1;
|
||||
|
@ -3724,7 +3844,7 @@ STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontd
|
|||
return return_value;
|
||||
}
|
||||
|
||||
STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, float font_size,
|
||||
STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size,
|
||||
int first_unicode_codepoint_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range)
|
||||
{
|
||||
stbtt_pack_range range;
|
||||
|
@ -3763,6 +3883,387 @@ STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int
|
|||
*xpos += b->xadvance;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// sdf computation
|
||||
//
|
||||
|
||||
#define STBTT_min(a,b) ((a) < (b) ? (a) : (b))
|
||||
#define STBTT_max(a,b) ((a) < (b) ? (b) : (a))
|
||||
|
||||
static int stbtt__ray_intersect_bezier(float orig[2], float ray[2], float q0[2], float q1[2], float q2[2], float hits[2][2])
|
||||
{
|
||||
float q0perp = q0[1]*ray[0] - q0[0]*ray[1];
|
||||
float q1perp = q1[1]*ray[0] - q1[0]*ray[1];
|
||||
float q2perp = q2[1]*ray[0] - q2[0]*ray[1];
|
||||
float roperp = orig[1]*ray[0] - orig[0]*ray[1];
|
||||
|
||||
float a = q0perp - 2*q1perp + q2perp;
|
||||
float b = q1perp - q0perp;
|
||||
float c = q0perp - roperp;
|
||||
|
||||
float s0 = 0., s1 = 0.;
|
||||
int num_s = 0;
|
||||
|
||||
if (a != 0.0) {
|
||||
float discr = b*b - a*c;
|
||||
if (discr > 0.0) {
|
||||
float rcpna = -1 / a;
|
||||
float d = (float) sqrt(discr);
|
||||
s0 = (b+d) * rcpna;
|
||||
s1 = (b-d) * rcpna;
|
||||
if (s0 >= 0.0 && s0 <= 1.0)
|
||||
num_s = 1;
|
||||
if (d > 0.0 && s1 >= 0.0 && s1 <= 1.0) {
|
||||
if (num_s == 0) s0 = s1;
|
||||
++num_s;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 2*b*s + c = 0
|
||||
// s = -c / (2*b)
|
||||
s0 = c / (-2 * b);
|
||||
if (s0 >= 0.0 && s0 <= 1.0)
|
||||
num_s = 1;
|
||||
}
|
||||
|
||||
if (num_s == 0)
|
||||
return 0;
|
||||
else {
|
||||
float rcp_len2 = 1 / (ray[0]*ray[0] + ray[1]*ray[1]);
|
||||
float rayn_x = ray[0] * rcp_len2, rayn_y = ray[1] * rcp_len2;
|
||||
|
||||
float q0d = q0[0]*rayn_x + q0[1]*rayn_y;
|
||||
float q1d = q1[0]*rayn_x + q1[1]*rayn_y;
|
||||
float q2d = q2[0]*rayn_x + q2[1]*rayn_y;
|
||||
float rod = orig[0]*rayn_x + orig[1]*rayn_y;
|
||||
|
||||
float q10d = q1d - q0d;
|
||||
float q20d = q2d - q0d;
|
||||
float q0rd = q0d - rod;
|
||||
|
||||
hits[0][0] = q0rd + s0*(2.0f - 2.0f*s0)*q10d + s0*s0*q20d;
|
||||
hits[0][1] = a*s0+b;
|
||||
|
||||
if (num_s > 1) {
|
||||
hits[1][0] = q0rd + s1*(2.0f - 2.0f*s1)*q10d + s1*s1*q20d;
|
||||
hits[1][1] = a*s1+b;
|
||||
return 2;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int equal(float *a, float *b)
|
||||
{
|
||||
return (a[0] == b[0] && a[1] == b[1]);
|
||||
}
|
||||
|
||||
static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex *verts)
|
||||
{
|
||||
int i;
|
||||
float orig[2], ray[2] = { 1, 0 };
|
||||
float y_frac;
|
||||
int winding = 0;
|
||||
|
||||
orig[0] = x;
|
||||
orig[1] = y;
|
||||
|
||||
// make sure y never passes through a vertex of the shape
|
||||
y_frac = (float) fmod(y, 1.0f);
|
||||
if (y_frac < 0.01f)
|
||||
y += 0.01f;
|
||||
else if (y_frac > 0.99f)
|
||||
y -= 0.01f;
|
||||
orig[1] = y;
|
||||
|
||||
// test a ray from (-infinity,y) to (x,y)
|
||||
for (i=0; i < nverts; ++i) {
|
||||
if (verts[i].type == STBTT_vline) {
|
||||
int x0 = (int) verts[i-1].x, y0 = (int) verts[i-1].y;
|
||||
int x1 = (int) verts[i ].x, y1 = (int) verts[i ].y;
|
||||
if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) {
|
||||
float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0;
|
||||
if (x_inter < x)
|
||||
winding += (y0 < y1) ? 1 : -1;
|
||||
}
|
||||
}
|
||||
if (verts[i].type == STBTT_vcurve) {
|
||||
int x0 = (int) verts[i-1].x , y0 = (int) verts[i-1].y ;
|
||||
int x1 = (int) verts[i ].cx, y1 = (int) verts[i ].cy;
|
||||
int x2 = (int) verts[i ].x , y2 = (int) verts[i ].y ;
|
||||
int ax = STBTT_min(x0,STBTT_min(x1,x2)), ay = STBTT_min(y0,STBTT_min(y1,y2));
|
||||
int by = STBTT_max(y0,STBTT_max(y1,y2));
|
||||
if (y > ay && y < by && x > ax) {
|
||||
float q0[2],q1[2],q2[2];
|
||||
float hits[2][2];
|
||||
q0[0] = (float)x0;
|
||||
q0[1] = (float)y0;
|
||||
q1[0] = (float)x1;
|
||||
q1[1] = (float)y1;
|
||||
q2[0] = (float)x2;
|
||||
q2[1] = (float)y2;
|
||||
if (equal(q0,q1) || equal(q1,q2)) {
|
||||
x0 = (int)verts[i-1].x;
|
||||
y0 = (int)verts[i-1].y;
|
||||
x1 = (int)verts[i ].x;
|
||||
y1 = (int)verts[i ].y;
|
||||
if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) {
|
||||
float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0;
|
||||
if (x_inter < x)
|
||||
winding += (y0 < y1) ? 1 : -1;
|
||||
}
|
||||
} else {
|
||||
int num_hits = stbtt__ray_intersect_bezier(orig, ray, q0, q1, q2, hits);
|
||||
if (num_hits >= 1)
|
||||
if (hits[0][0] < 0)
|
||||
winding += (hits[0][1] < 0 ? -1 : 1);
|
||||
if (num_hits >= 2)
|
||||
if (hits[1][0] < 0)
|
||||
winding += (hits[1][1] < 0 ? -1 : 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return winding;
|
||||
}
|
||||
|
||||
static float stbtt__cuberoot( float x )
|
||||
{
|
||||
if (x<0)
|
||||
return -(float) STBTT_pow(-x,1.0f/3.0f);
|
||||
else
|
||||
return (float) STBTT_pow( x,1.0f/3.0f);
|
||||
}
|
||||
|
||||
// x^3 + c*x^2 + b*x + a = 0
|
||||
static int stbtt__solve_cubic(float a, float b, float c, float* r)
|
||||
{
|
||||
float s = -a / 3;
|
||||
float p = b - a*a / 3;
|
||||
float q = a * (2*a*a - 9*b) / 27 + c;
|
||||
float p3 = p*p*p;
|
||||
float d = q*q + 4*p3 / 27;
|
||||
if (d >= 0) {
|
||||
float z = (float) STBTT_sqrt(d);
|
||||
float u = (-q + z) / 2;
|
||||
float v = (-q - z) / 2;
|
||||
u = stbtt__cuberoot(u);
|
||||
v = stbtt__cuberoot(v);
|
||||
r[0] = s + u + v;
|
||||
return 1;
|
||||
} else {
|
||||
float u = (float) STBTT_sqrt(-p/3);
|
||||
float v = (float) STBTT_acos(-STBTT_sqrt(-27/p3) * q / 2) / 3; // p3 must be negative, since d is negative
|
||||
float m = (float) STBTT_cos(v);
|
||||
float n = (float) STBTT_cos(v-3.141592/2)*1.732050808f;
|
||||
r[0] = s + u * 2 * m;
|
||||
r[1] = s - u * (m + n);
|
||||
r[2] = s - u * (m - n);
|
||||
|
||||
//STBTT_assert( STBTT_fabs(((r[0]+a)*r[0]+b)*r[0]+c) < 0.05f); // these asserts may not be safe at all scales, though they're in bezier t parameter units so maybe?
|
||||
//STBTT_assert( STBTT_fabs(((r[1]+a)*r[1]+b)*r[1]+c) < 0.05f);
|
||||
//STBTT_assert( STBTT_fabs(((r[2]+a)*r[2]+b)*r[2]+c) < 0.05f);
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
|
||||
STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff)
|
||||
{
|
||||
float scale_x = scale, scale_y = scale;
|
||||
int ix0,iy0,ix1,iy1;
|
||||
int w,h;
|
||||
unsigned char *data;
|
||||
|
||||
// if one scale is 0, use same scale for both
|
||||
if (scale_x == 0) scale_x = scale_y;
|
||||
if (scale_y == 0) {
|
||||
if (scale_x == 0) return NULL; // if both scales are 0, return NULL
|
||||
scale_y = scale_x;
|
||||
}
|
||||
|
||||
stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale, scale, 0.0f,0.0f, &ix0,&iy0,&ix1,&iy1);
|
||||
|
||||
// if empty, return NULL
|
||||
if (ix0 == ix1 || iy0 == iy1)
|
||||
return NULL;
|
||||
|
||||
ix0 -= padding;
|
||||
iy0 -= padding;
|
||||
ix1 += padding;
|
||||
iy1 += padding;
|
||||
|
||||
w = (ix1 - ix0);
|
||||
h = (iy1 - iy0);
|
||||
|
||||
if (width ) *width = w;
|
||||
if (height) *height = h;
|
||||
if (xoff ) *xoff = ix0;
|
||||
if (yoff ) *yoff = iy0;
|
||||
|
||||
// invert for y-downwards bitmaps
|
||||
scale_y = -scale_y;
|
||||
|
||||
{
|
||||
int x,y,i,j;
|
||||
float *precompute;
|
||||
stbtt_vertex *verts;
|
||||
int num_verts = stbtt_GetGlyphShape(info, glyph, &verts);
|
||||
data = (unsigned char *) STBTT_malloc(w * h, info->userdata);
|
||||
precompute = (float *) STBTT_malloc(num_verts * sizeof(float), info->userdata);
|
||||
|
||||
for (i=0,j=num_verts-1; i < num_verts; j=i++) {
|
||||
if (verts[i].type == STBTT_vline) {
|
||||
float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y;
|
||||
float x1 = verts[j].x*scale_x, y1 = verts[j].y*scale_y;
|
||||
float dist = (float) STBTT_sqrt((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0));
|
||||
precompute[i] = (dist == 0) ? 0.0f : 1.0f / dist;
|
||||
} else if (verts[i].type == STBTT_vcurve) {
|
||||
float x2 = verts[j].x *scale_x, y2 = verts[j].y *scale_y;
|
||||
float x1 = verts[i].cx*scale_x, y1 = verts[i].cy*scale_y;
|
||||
float x0 = verts[i].x *scale_x, y0 = verts[i].y *scale_y;
|
||||
float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2;
|
||||
float len2 = bx*bx + by*by;
|
||||
if (len2 != 0.0f)
|
||||
precompute[i] = 1.0f / (bx*bx + by*by);
|
||||
else
|
||||
precompute[i] = 0.0f;
|
||||
} else
|
||||
precompute[i] = 0.0f;
|
||||
}
|
||||
|
||||
for (y=iy0; y < iy1; ++y) {
|
||||
for (x=ix0; x < ix1; ++x) {
|
||||
float val;
|
||||
float min_dist = 999999.0f;
|
||||
float sx = (float) x + 0.5f;
|
||||
float sy = (float) y + 0.5f;
|
||||
float x_gspace = (sx / scale_x);
|
||||
float y_gspace = (sy / scale_y);
|
||||
|
||||
int winding = stbtt__compute_crossings_x(x_gspace, y_gspace, num_verts, verts); // @OPTIMIZE: this could just be a rasterization, but needs to be line vs. non-tesselated curves so a new path
|
||||
|
||||
for (i=0; i < num_verts; ++i) {
|
||||
float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y;
|
||||
|
||||
// check against every point here rather than inside line/curve primitives -- @TODO: wrong if multiple 'moves' in a row produce a garbage point, and given culling, probably more efficient to do within line/curve
|
||||
float dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy);
|
||||
if (dist2 < min_dist*min_dist)
|
||||
min_dist = (float) STBTT_sqrt(dist2);
|
||||
|
||||
if (verts[i].type == STBTT_vline) {
|
||||
float x1 = verts[i-1].x*scale_x, y1 = verts[i-1].y*scale_y;
|
||||
|
||||
// coarse culling against bbox
|
||||
//if (sx > STBTT_min(x0,x1)-min_dist && sx < STBTT_max(x0,x1)+min_dist &&
|
||||
// sy > STBTT_min(y0,y1)-min_dist && sy < STBTT_max(y0,y1)+min_dist)
|
||||
float dist = (float) STBTT_fabs((x1-x0)*(y0-sy) - (y1-y0)*(x0-sx)) * precompute[i];
|
||||
STBTT_assert(i != 0);
|
||||
if (dist < min_dist) {
|
||||
// check position along line
|
||||
// x' = x0 + t*(x1-x0), y' = y0 + t*(y1-y0)
|
||||
// minimize (x'-sx)*(x'-sx)+(y'-sy)*(y'-sy)
|
||||
float dx = x1-x0, dy = y1-y0;
|
||||
float px = x0-sx, py = y0-sy;
|
||||
// minimize (px+t*dx)^2 + (py+t*dy)^2 = px*px + 2*px*dx*t + t^2*dx*dx + py*py + 2*py*dy*t + t^2*dy*dy
|
||||
// derivative: 2*px*dx + 2*py*dy + (2*dx*dx+2*dy*dy)*t, set to 0 and solve
|
||||
float t = -(px*dx + py*dy) / (dx*dx + dy*dy);
|
||||
if (t >= 0.0f && t <= 1.0f)
|
||||
min_dist = dist;
|
||||
}
|
||||
} else if (verts[i].type == STBTT_vcurve) {
|
||||
float x2 = verts[i-1].x *scale_x, y2 = verts[i-1].y *scale_y;
|
||||
float x1 = verts[i ].cx*scale_x, y1 = verts[i ].cy*scale_y;
|
||||
float box_x0 = STBTT_min(STBTT_min(x0,x1),x2);
|
||||
float box_y0 = STBTT_min(STBTT_min(y0,y1),y2);
|
||||
float box_x1 = STBTT_max(STBTT_max(x0,x1),x2);
|
||||
float box_y1 = STBTT_max(STBTT_max(y0,y1),y2);
|
||||
// coarse culling against bbox to avoid computing cubic unnecessarily
|
||||
if (sx > box_x0-min_dist && sx < box_x1+min_dist && sy > box_y0-min_dist && sy < box_y1+min_dist) {
|
||||
int num=0;
|
||||
float ax = x1-x0, ay = y1-y0;
|
||||
float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2;
|
||||
float mx = x0 - sx, my = y0 - sy;
|
||||
float res[3],px,py,t,it;
|
||||
float a_inv = precompute[i];
|
||||
if (a_inv == 0.0) { // if a_inv is 0, it's 2nd degree so use quadratic formula
|
||||
float a = 3*(ax*bx + ay*by);
|
||||
float b = 2*(ax*ax + ay*ay) + (mx*bx+my*by);
|
||||
float c = mx*ax+my*ay;
|
||||
if (a == 0.0) { // if a is 0, it's linear
|
||||
if (b != 0.0) {
|
||||
res[num++] = -c/b;
|
||||
}
|
||||
} else {
|
||||
float discriminant = b*b - 4*a*c;
|
||||
if (discriminant < 0)
|
||||
num = 0;
|
||||
else {
|
||||
float root = (float) STBTT_sqrt(discriminant);
|
||||
res[0] = (-b - root)/(2*a);
|
||||
res[1] = (-b + root)/(2*a);
|
||||
num = 2; // don't bother distinguishing 1-solution case, as code below will still work
|
||||
}
|
||||
}
|
||||
} else {
|
||||
float b = 3*(ax*bx + ay*by) * a_inv; // could precompute this as it doesn't depend on sample point
|
||||
float c = (2*(ax*ax + ay*ay) + (mx*bx+my*by)) * a_inv;
|
||||
float d = (mx*ax+my*ay) * a_inv;
|
||||
num = stbtt__solve_cubic(b, c, d, res);
|
||||
}
|
||||
if (num >= 1 && res[0] >= 0.0f && res[0] <= 1.0f) {
|
||||
t = res[0], it = 1.0f - t;
|
||||
px = it*it*x0 + 2*t*it*x1 + t*t*x2;
|
||||
py = it*it*y0 + 2*t*it*y1 + t*t*y2;
|
||||
dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy);
|
||||
if (dist2 < min_dist * min_dist)
|
||||
min_dist = (float) STBTT_sqrt(dist2);
|
||||
}
|
||||
if (num >= 2 && res[1] >= 0.0f && res[1] <= 1.0f) {
|
||||
t = res[1], it = 1.0f - t;
|
||||
px = it*it*x0 + 2*t*it*x1 + t*t*x2;
|
||||
py = it*it*y0 + 2*t*it*y1 + t*t*y2;
|
||||
dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy);
|
||||
if (dist2 < min_dist * min_dist)
|
||||
min_dist = (float) STBTT_sqrt(dist2);
|
||||
}
|
||||
if (num >= 3 && res[2] >= 0.0f && res[2] <= 1.0f) {
|
||||
t = res[2], it = 1.0f - t;
|
||||
px = it*it*x0 + 2*t*it*x1 + t*t*x2;
|
||||
py = it*it*y0 + 2*t*it*y1 + t*t*y2;
|
||||
dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy);
|
||||
if (dist2 < min_dist * min_dist)
|
||||
min_dist = (float) STBTT_sqrt(dist2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (winding == 0)
|
||||
min_dist = -min_dist; // if outside the shape, value is negative
|
||||
val = onedge_value + pixel_dist_scale * min_dist;
|
||||
if (val < 0)
|
||||
val = 0;
|
||||
else if (val > 255)
|
||||
val = 255;
|
||||
data[(y-iy0)*w+(x-ix0)] = (unsigned char) val;
|
||||
}
|
||||
}
|
||||
STBTT_free(precompute, info->userdata);
|
||||
STBTT_free(verts, info->userdata);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff)
|
||||
{
|
||||
return stbtt_GetGlyphSDF(info, scale, stbtt_FindGlyphIndex(info, codepoint), padding, onedge_value, pixel_dist_scale, width, height, xoff, yoff);
|
||||
}
|
||||
|
||||
STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata)
|
||||
{
|
||||
STBTT_free(bitmap, userdata);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
@ -3970,6 +4471,10 @@ STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const
|
|||
|
||||
// FULL VERSION HISTORY
|
||||
//
|
||||
// 1.16 (2017-07-12) SDF support
|
||||
// 1.15 (2017-03-03) make more arguments const
|
||||
// 1.14 (2017-01-16) num-fonts-in-TTC function
|
||||
// 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts
|
||||
// 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual
|
||||
// 1.11 (2016-04-02) fix unused-variable warning
|
||||
// 1.10 (2016-04-02) allow user-defined fabs() replacement
|
||||
|
|
1
raylib/external/stb_vorbis.c
vendored
1
raylib/external/stb_vorbis.c
vendored
|
@ -193,6 +193,7 @@
|
|||
#undef __forceinline
|
||||
#endif
|
||||
#define __forceinline
|
||||
#define alloca __builtin_alloca
|
||||
#elif !defined(_MSC_VER)
|
||||
#if __GNUC__
|
||||
#define __forceinline inline
|
||||
|
|
5
raylib/external/stb_vorbis.h
vendored
5
raylib/external/stb_vorbis.h
vendored
|
@ -1,4 +1,4 @@
|
|||
// Ogg Vorbis audio decoder - v1.10 - public domain
|
||||
// Ogg Vorbis audio decoder - v1.11 - public domain
|
||||
// http://nothings.org/stb_vorbis/
|
||||
//
|
||||
// Original version written by Sean Barrett in 2007.
|
||||
|
@ -29,9 +29,10 @@
|
|||
// Bernhard Wodo Evan Balster alxprd@github
|
||||
// Tom Beaumont Ingo Leitgeb Nicolas Guillemot
|
||||
// Phillip Bennefall Rohit Thiago Goulart
|
||||
// manxorist@github saga musix
|
||||
// manxorist@github saga musix github:infatum
|
||||
//
|
||||
// Partial history:
|
||||
// 1.11 - 2017/07/23 - fix MinGW compilation
|
||||
// 1.10 - 2017/03/03 - more robust seeking; fix negative ilog(); clear error in open_memory
|
||||
// 1.09 - 2016/04/04 - back out 'truncation of last frame' fix from previous version
|
||||
// 1.08 - 2016/04/02 - warnings; setup memory leaks; truncation of last frame
|
||||
|
|
|
@ -148,8 +148,9 @@ float GetGesturePinchAngle(void); // Get gesture pinch ang
|
|||
int __stdcall QueryPerformanceCounter(unsigned long long int *lpPerformanceCount);
|
||||
int __stdcall QueryPerformanceFrequency(unsigned long long int *lpFrequency);
|
||||
#elif defined(__linux__)
|
||||
#include <sys/time.h> // Required for: timespec
|
||||
#include <time.h> // Required for: clock_gettime()
|
||||
//#define _POSIX_C_SOURCE 199309L // Required for CLOCK_MONOTONIC if compiled with c99 without gnu ext.
|
||||
#include <sys/time.h> // Required for: timespec
|
||||
#include <time.h> // Required for: clock_gettime()
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
|
|
1060
raylib/models.c
1060
raylib/models.c
File diff suppressed because it is too large
Load diff
244
raylib/models.go
244
raylib/models.go
|
@ -6,7 +6,66 @@ package raylib
|
|||
*/
|
||||
import "C"
|
||||
import "unsafe"
|
||||
import "reflect"
|
||||
|
||||
// Shader location point type
|
||||
const (
|
||||
LocVertexPosition = iota
|
||||
LocVertexTexcoord01
|
||||
LocVertexTexcoord02
|
||||
LocVertexNormal
|
||||
LocVertexTangent
|
||||
LocVertexColor
|
||||
LocMatrixMvp
|
||||
LocMatrixModel
|
||||
LocMatrixView
|
||||
LocMatrixProjection
|
||||
LocVectorView
|
||||
LocColorDiffuse
|
||||
LocColorSpecular
|
||||
LocColorAmbient
|
||||
LocMapAlbedo
|
||||
LocMapMetalness
|
||||
LocMapNormal
|
||||
LocMapRoughness
|
||||
LocMapOccusion
|
||||
LocMapEmission
|
||||
LocMapHeight
|
||||
LocMapCubemap
|
||||
LocMapIrradiance
|
||||
LocMapPrefilter
|
||||
LocMapBrdf
|
||||
)
|
||||
|
||||
// Material map type
|
||||
const (
|
||||
// MapDiffuse
|
||||
MapAlbedo = iota
|
||||
MapMetalness
|
||||
MapNormal
|
||||
MapRoughness
|
||||
MapOcclusion
|
||||
MapEmission
|
||||
MapHeight
|
||||
// NOTE: Uses GL_TEXTURE_CUBE_MAP
|
||||
MapCubemap
|
||||
// NOTE: Uses GL_TEXTURE_CUBE_MAP
|
||||
MapIrradiance
|
||||
// NOTE: Uses GL_TEXTURE_CUBE_MAP
|
||||
MapPrefilter
|
||||
MapBrdf
|
||||
)
|
||||
|
||||
const (
|
||||
MapDiffuse = MapAlbedo
|
||||
MapSpecular = MapMetalness
|
||||
LocMapDiffuse = LocMapAlbedo
|
||||
LocMapSpecular = LocMapMetalness
|
||||
)
|
||||
|
||||
const (
|
||||
MaxShaderLocations = 32
|
||||
MaxMaterialMaps = 12
|
||||
)
|
||||
|
||||
// Mesh - Vertex data definning a mesh
|
||||
type Mesh struct {
|
||||
|
@ -50,22 +109,14 @@ func NewMeshFromPointer(ptr unsafe.Pointer) Mesh {
|
|||
|
||||
// Material type
|
||||
type Material struct {
|
||||
// Standard shader (supports 3 map textures)
|
||||
// Shader
|
||||
Shader Shader
|
||||
// Diffuse texture (binded to shader mapTexture0Loc)
|
||||
TexDiffuse Texture2D
|
||||
// Normal texture (binded to shader mapTexture1Loc)
|
||||
TexNormal Texture2D
|
||||
// Specular texture (binded to shader mapTexture2Loc)
|
||||
TexSpecular Texture2D
|
||||
// Diffuse color
|
||||
ColDiffuse Color
|
||||
// Ambient color
|
||||
ColAmbient Color
|
||||
// Specular color
|
||||
ColSpecular Color
|
||||
// Glossiness level (Ranges from 0 to 1000)
|
||||
Glossiness float32
|
||||
// Maps
|
||||
Maps [MaxMaterialMaps]MaterialMap
|
||||
// Padding
|
||||
_ [4]byte
|
||||
// Generic parameters (if required)
|
||||
Params *[]float32
|
||||
}
|
||||
|
||||
func (m *Material) cptr() *C.Material {
|
||||
|
@ -73,8 +124,8 @@ func (m *Material) cptr() *C.Material {
|
|||
}
|
||||
|
||||
// NewMaterial - Returns new Material
|
||||
func NewMaterial(shader Shader, texDiffuse, texNormal, texSpecular Texture2D, colDiffuse, colAmbient, colSpecular Color, glossiness float32) Material {
|
||||
return Material{shader, texDiffuse, texNormal, texSpecular, colDiffuse, colAmbient, colSpecular, glossiness}
|
||||
func NewMaterial(shader Shader, maps [MaxMaterialMaps]MaterialMap, params *[]float32) Material {
|
||||
return Material{shader, maps, [4]byte{}, params}
|
||||
}
|
||||
|
||||
// NewMaterialFromPointer - Returns new Material from pointer
|
||||
|
@ -82,6 +133,16 @@ func NewMaterialFromPointer(ptr unsafe.Pointer) Material {
|
|||
return *(*Material)(ptr)
|
||||
}
|
||||
|
||||
// MaterialMap type
|
||||
type MaterialMap struct {
|
||||
// Texture
|
||||
Texture Texture2D
|
||||
// Color
|
||||
Color Color
|
||||
// Value
|
||||
Value float32
|
||||
}
|
||||
|
||||
// Model type
|
||||
type Model struct {
|
||||
// Vertex data buffers (RAM and VRAM)
|
||||
|
@ -274,18 +335,6 @@ func LoadMesh(fileName string) Mesh {
|
|||
return v
|
||||
}
|
||||
|
||||
// LoadMeshEx - Load mesh from vertex data
|
||||
func LoadMeshEx(numVertex int32, vData []float32, vtData []float32, vnData []float32, cData []Color) Mesh {
|
||||
cnumVertex := (C.int)(numVertex)
|
||||
cvData := (*C.float)(unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(&vData)).Data))
|
||||
cvtData := (*C.float)(unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(&vtData)).Data))
|
||||
cvnData := (*C.float)(unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(&vnData)).Data))
|
||||
ccData := (*C.Color)(unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(&cData)).Data))
|
||||
ret := C.LoadMeshEx(cnumVertex, cvData, cvtData, cvnData, ccData)
|
||||
v := NewMeshFromPointer(unsafe.Pointer(&ret))
|
||||
return v
|
||||
}
|
||||
|
||||
// LoadModel - Load model from file
|
||||
func LoadModel(fileName string) Model {
|
||||
cfileName := C.CString(fileName)
|
||||
|
@ -296,32 +345,17 @@ func LoadModel(fileName string) Model {
|
|||
}
|
||||
|
||||
// LoadModelFromMesh - Load model from mesh data
|
||||
func LoadModelFromMesh(data Mesh, dynamic bool) Model {
|
||||
func LoadModelFromMesh(data Mesh) Model {
|
||||
cdata := data.cptr()
|
||||
cdynamic := 0
|
||||
if dynamic {
|
||||
cdynamic = 1
|
||||
}
|
||||
ret := C.LoadModelFromMesh(*cdata, C.bool(cdynamic))
|
||||
ret := C.LoadModelFromMesh(*cdata)
|
||||
v := NewModelFromPointer(unsafe.Pointer(&ret))
|
||||
return v
|
||||
}
|
||||
|
||||
// LoadHeightmap - Load heightmap model from image data
|
||||
func LoadHeightmap(heightmap *Image, size Vector3) Model {
|
||||
cheightmap := heightmap.cptr()
|
||||
csize := size.cptr()
|
||||
ret := C.LoadHeightmap(*cheightmap, *csize)
|
||||
v := NewModelFromPointer(unsafe.Pointer(&ret))
|
||||
return v
|
||||
}
|
||||
|
||||
// LoadCubicmap - Load cubes-based map model from image data
|
||||
func LoadCubicmap(cubicmap *Image) Model {
|
||||
ccubicmap := cubicmap.cptr()
|
||||
ret := C.LoadCubicmap(*ccubicmap)
|
||||
v := NewModelFromPointer(unsafe.Pointer(&ret))
|
||||
return v
|
||||
// UnloadModel - Unload model from memory (RAM and/or VRAM)
|
||||
func UnloadModel(model Model) {
|
||||
cmodel := model.cptr()
|
||||
C.UnloadModel(*cmodel)
|
||||
}
|
||||
|
||||
// UnloadMesh - Unload mesh from memory (RAM and/or VRAM)
|
||||
|
@ -330,10 +364,104 @@ func UnloadMesh(mesh *Mesh) {
|
|||
C.UnloadMesh(cmesh)
|
||||
}
|
||||
|
||||
// UnloadModel - Unload model from memory (RAM and/or VRAM)
|
||||
func UnloadModel(model Model) {
|
||||
cmodel := model.cptr()
|
||||
C.UnloadModel(*cmodel)
|
||||
// GenMeshPlane - Generate plane mesh (with subdivisions)
|
||||
func GenMeshPlane(width, length float32, resX, resZ int) Mesh {
|
||||
cwidth := (C.float)(width)
|
||||
clength := (C.float)(length)
|
||||
cresX := (C.int)(resX)
|
||||
cresZ := (C.int)(resZ)
|
||||
|
||||
ret := C.GenMeshPlane(cwidth, clength, cresX, cresZ)
|
||||
v := NewMeshFromPointer(unsafe.Pointer(&ret))
|
||||
return v
|
||||
}
|
||||
|
||||
// GenMeshCube - Generate cuboid mesh
|
||||
func GenMeshCube(width, height, length float32) Mesh {
|
||||
cwidth := (C.float)(width)
|
||||
cheight := (C.float)(height)
|
||||
clength := (C.float)(length)
|
||||
|
||||
ret := C.GenMeshCube(cwidth, cheight, clength)
|
||||
v := NewMeshFromPointer(unsafe.Pointer(&ret))
|
||||
return v
|
||||
}
|
||||
|
||||
// GenMeshSphere - Generate sphere mesh (standard sphere)
|
||||
func GenMeshSphere(radius float32, rings, slices int) Mesh {
|
||||
cradius := (C.float)(radius)
|
||||
crings := (C.int)(rings)
|
||||
cslices := (C.int)(slices)
|
||||
|
||||
ret := C.GenMeshSphere(cradius, crings, cslices)
|
||||
v := NewMeshFromPointer(unsafe.Pointer(&ret))
|
||||
return v
|
||||
}
|
||||
|
||||
// GenMeshHemiSphere - Generate half-sphere mesh (no bottom cap)
|
||||
func GenMeshHemiSphere(radius float32, rings, slices int) Mesh {
|
||||
cradius := (C.float)(radius)
|
||||
crings := (C.int)(rings)
|
||||
cslices := (C.int)(slices)
|
||||
|
||||
ret := C.GenMeshHemiSphere(cradius, crings, cslices)
|
||||
v := NewMeshFromPointer(unsafe.Pointer(&ret))
|
||||
return v
|
||||
}
|
||||
|
||||
// GenMeshCylinder - Generate cylinder mesh
|
||||
func GenMeshCylinder(radius, height float32, slices int) Mesh {
|
||||
cradius := (C.float)(radius)
|
||||
cheight := (C.float)(height)
|
||||
cslices := (C.int)(slices)
|
||||
|
||||
ret := C.GenMeshCylinder(cradius, cheight, cslices)
|
||||
v := NewMeshFromPointer(unsafe.Pointer(&ret))
|
||||
return v
|
||||
}
|
||||
|
||||
// GenMeshTorus - Generate torus mesh
|
||||
func GenMeshTorus(radius, size float32, radSeg, sides int) Mesh {
|
||||
cradius := (C.float)(radius)
|
||||
csize := (C.float)(size)
|
||||
cradSeg := (C.int)(radSeg)
|
||||
csides := (C.int)(sides)
|
||||
|
||||
ret := C.GenMeshTorus(cradius, csize, cradSeg, csides)
|
||||
v := NewMeshFromPointer(unsafe.Pointer(&ret))
|
||||
return v
|
||||
}
|
||||
|
||||
// GenMeshKnot - Generate trefoil knot mesh
|
||||
func GenMeshKnot(radius, size float32, radSeg, sides int) Mesh {
|
||||
cradius := (C.float)(radius)
|
||||
csize := (C.float)(size)
|
||||
cradSeg := (C.int)(radSeg)
|
||||
csides := (C.int)(sides)
|
||||
|
||||
ret := C.GenMeshKnot(cradius, csize, cradSeg, csides)
|
||||
v := NewMeshFromPointer(unsafe.Pointer(&ret))
|
||||
return v
|
||||
}
|
||||
|
||||
// GenMeshHeightmap - Generate heightmap mesh from image data
|
||||
func GenMeshHeightmap(heightmap Image, size Vector3) Mesh {
|
||||
cheightmap := heightmap.cptr()
|
||||
csize := size.cptr()
|
||||
|
||||
ret := C.GenMeshHeightmap(*cheightmap, *csize)
|
||||
v := NewMeshFromPointer(unsafe.Pointer(&ret))
|
||||
return v
|
||||
}
|
||||
|
||||
// GenMeshCubicmap - Generate cubes-based map mesh from image data
|
||||
func GenMeshCubicmap(cubicmap Image, size Vector3) Mesh {
|
||||
ccubicmap := cubicmap.cptr()
|
||||
csize := size.cptr()
|
||||
|
||||
ret := C.GenMeshCubicmap(*ccubicmap, *csize)
|
||||
v := NewMeshFromPointer(unsafe.Pointer(&ret))
|
||||
return v
|
||||
}
|
||||
|
||||
// LoadMaterial - Load material data (.MTL)
|
||||
|
@ -345,9 +473,9 @@ func LoadMaterial(fileName string) Material {
|
|||
return v
|
||||
}
|
||||
|
||||
// LoadDefaultMaterial - Load default material (uses default models shader)
|
||||
func LoadDefaultMaterial() Material {
|
||||
ret := C.LoadDefaultMaterial()
|
||||
// LoadMaterialDefault - Load default material (Supports: DIFFUSE, SPECULAR, NORMAL maps)
|
||||
func LoadMaterialDefault() Material {
|
||||
ret := C.LoadMaterialDefault()
|
||||
v := NewMaterialFromPointer(unsafe.Pointer(&ret))
|
||||
return v
|
||||
}
|
||||
|
|
416
raylib/raylib.h
416
raylib/raylib.h
|
@ -1,30 +1,29 @@
|
|||
/**********************************************************************************************
|
||||
/**********************************************************************************************
|
||||
*
|
||||
* raylib v1.7.0
|
||||
* raylib v1.8.0
|
||||
*
|
||||
* A simple and easy-to-use library to learn videogames programming (www.raylib.com)
|
||||
*
|
||||
* FEATURES:
|
||||
* - Library written in plain C code (C99)
|
||||
* - Uses PascalCase/camelCase notation
|
||||
* - Written in plain C code (C99) in PascalCase/camelCase notation
|
||||
* - Multiple platforms support: Windows, Linux, Mac, Android, Raspberry Pi and HTML5
|
||||
* - Hardware accelerated with OpenGL (1.1, 2.1, 3.3 or ES 2.0)
|
||||
* - Unique OpenGL abstraction layer (usable as standalone module): [rlgl]
|
||||
* - Powerful fonts module with SpriteFonts support (XNA bitmap fonts, AngelCode fonts, TTF)
|
||||
* - Multiple textures support, including compressed formats and mipmaps generation
|
||||
* - Basic 3d support for Shapes, Models, Billboards, Heightmaps and Cubicmaps
|
||||
* - Powerful math module for Vector, Matrix and Quaternion operations: [raymath]
|
||||
* - Outstanding texture formats support, including compressed formats (DXT, ETC, PVRT, ASTC)
|
||||
* - Basic 3d support for Geometrics, Models, Billboards, Heightmaps and Cubicmaps
|
||||
* - Flexible Materials system, supporting classic maps and PBR maps
|
||||
* - Shaders support, including Model shaders and Postprocessing shaders
|
||||
* - Powerful math module for Vector2, Vector3, Matrix and Quaternion operations: [raymath]
|
||||
* - Audio loading and playing with streaming support and mixing channels: [audio]
|
||||
* - VR stereo rendering support with configurable HMD device parameters
|
||||
* - Multiple platforms support: Windows, Linux, Mac, Android, Raspberry Pi, HTML5 and Oculus Rift CV1
|
||||
* - Custom color palette for fancy visuals on raywhite background
|
||||
* - Minimal external dependencies (GLFW3, OpenGL, OpenAL)
|
||||
* - Complete bindings for Lua, Go and Pascal
|
||||
* - Complete bindings to LUA (raylib-lua) and Go (raylib-go)
|
||||
*
|
||||
* NOTES:
|
||||
* 32bit Colors - All defined color are always RGBA (struct Color is 4 byte)
|
||||
* One custom default font could be loaded automatically when InitWindow() [core]
|
||||
* One custom font is loaded by default when InitWindow() [core]
|
||||
* If using OpenGL 3.3 or ES2, one default shader is loaded automatically (internally defined) [rlgl]
|
||||
* If using OpenGL 3.3 or ES2, several vertex buffers (VAO/VBO) are created to manage lines-triangles-quads
|
||||
* If using OpenGL 3.3 or ES2, two default shaders could be loaded automatically (internally defined)
|
||||
*
|
||||
* DEPENDENCIES:
|
||||
* GLFW3 (www.glfw.org) for window/context management and input [core]
|
||||
|
@ -33,12 +32,16 @@
|
|||
*
|
||||
* OPTIONAL DEPENDENCIES:
|
||||
* stb_image (Sean Barret) for images loading (JPEG, PNG, BMP, TGA) [textures]
|
||||
* stb_image_resize (Sean Barret) for image resizing algorythms [textures]
|
||||
* stb_image_write (Sean Barret) for image writting (PNG) [utils]
|
||||
* stb_truetype (Sean Barret) for ttf fonts loading [text]
|
||||
* stb_vorbis (Sean Barret) for ogg audio loading [audio]
|
||||
* stb_perlin (Sean Barret) for Perlin noise image generation [textures]
|
||||
* par_shapes (Philip Rideout) for parametric 3d shapes generation [models]
|
||||
* jar_xm (Joshua Reisenauer) for XM audio module loading [audio]
|
||||
* jar_mod (Joshua Reisenauer) for MOD audio module loading [audio]
|
||||
* dr_flac (David Reid) for FLAC audio file loading [audio]
|
||||
* rgif (Charlie Tangora, Ramon Santamaria) for GIF recording [core]
|
||||
* tinfl for data decompression (DEFLATE algorithm) [rres]
|
||||
*
|
||||
*
|
||||
|
@ -76,14 +79,17 @@
|
|||
//#define PLATFORM_WEB // HTML5 (emscripten, asm.js)
|
||||
|
||||
// Security check in case no PLATFORM_* defined
|
||||
#if !defined(PLATFORM_DESKTOP) && !defined(PLATFORM_ANDROID) && !defined(PLATFORM_RPI) && !defined(PLATFORM_WEB)
|
||||
#define PLATFORM_DESKTOP
|
||||
#if !defined(PLATFORM_DESKTOP) && \
|
||||
!defined(PLATFORM_ANDROID) && \
|
||||
!defined(PLATFORM_RPI) && \
|
||||
!defined(PLATFORM_WEB)
|
||||
#define PLATFORM_DESKTOP
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && defined(BUILDING_DLL)
|
||||
#define RLAPI __declspec(dllexport) // We are building raylib as a Win32 DLL
|
||||
#elif defined(_WIN32) && defined(RAYLIB_DLL)
|
||||
#define RLAPI __declspec(dllimport) // We are using raylib as a Win32 DLL
|
||||
#if defined(_WIN32) && defined(BUILD_LIBTYPE_SHARED)
|
||||
#define RLAPI __declspec(dllexport) // We are building raylib as a Win32 shared library (.dll)
|
||||
#elif defined(_WIN32) && defined(USE_LIBTYPE_SHARED)
|
||||
#define RLAPI __declspec(dllimport) // We are using raylib as a Win32 shared library (.dll)
|
||||
#else
|
||||
#define RLAPI // We are building or using raylib as a static library (or Linux shared library)
|
||||
#endif
|
||||
|
@ -293,14 +299,17 @@
|
|||
#define MAGENTA CLITERAL{ 255, 0, 255, 255 } // Magenta
|
||||
#define RAYWHITE CLITERAL{ 245, 245, 245, 255 } // My own White (raylib logo)
|
||||
|
||||
// Shader and material limits
|
||||
#define MAX_SHADER_LOCATIONS 32 // Maximum number of predefined locations stored in shader struct
|
||||
#define MAX_MATERIAL_MAPS 12 // Maximum number of texture maps stored in shader struct
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Structures Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
#ifndef __cplusplus
|
||||
// Boolean type
|
||||
#if !defined(_STDBOOL_H)
|
||||
#ifndef bool
|
||||
typedef enum { false, true } bool;
|
||||
#define _STDBOOL_H
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -351,7 +360,7 @@ typedef struct Image {
|
|||
int format; // Data format (TextureFormat type)
|
||||
} Image;
|
||||
|
||||
// Texture2D type, bpp always RGBA (32bit)
|
||||
// Texture2D type
|
||||
// NOTE: Data stored in GPU memory
|
||||
typedef struct Texture2D {
|
||||
unsigned int id; // OpenGL texture id
|
||||
|
@ -403,63 +412,46 @@ typedef struct Camera2D {
|
|||
|
||||
// Bounding box type
|
||||
typedef struct BoundingBox {
|
||||
Vector3 min; // minimum vertex box-corner
|
||||
Vector3 max; // maximum vertex box-corner
|
||||
Vector3 min; // Minimum vertex box-corner
|
||||
Vector3 max; // Maximum vertex box-corner
|
||||
} BoundingBox;
|
||||
|
||||
// Vertex data definning a mesh
|
||||
// NOTE: Data stored in CPU memory (and GPU)
|
||||
typedef struct Mesh {
|
||||
int vertexCount; // number of vertices stored in arrays
|
||||
int triangleCount; // number of triangles stored (indexed or not)
|
||||
float *vertices; // vertex position (XYZ - 3 components per vertex) (shader-location = 0)
|
||||
float *texcoords; // vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1)
|
||||
float *texcoords2; // vertex second texture coordinates (useful for lightmaps) (shader-location = 5)
|
||||
float *normals; // vertex normals (XYZ - 3 components per vertex) (shader-location = 2)
|
||||
float *tangents; // vertex tangents (XYZ - 3 components per vertex) (shader-location = 4)
|
||||
unsigned char *colors; // vertex colors (RGBA - 4 components per vertex) (shader-location = 3)
|
||||
unsigned short *indices;// vertex indices (in case vertex data comes indexed)
|
||||
int vertexCount; // Number of vertices stored in arrays
|
||||
int triangleCount; // Number of triangles stored (indexed or not)
|
||||
|
||||
float *vertices; // Vertex position (XYZ - 3 components per vertex) (shader-location = 0)
|
||||
float *texcoords; // Vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1)
|
||||
float *texcoords2; // Vertex second texture coordinates (useful for lightmaps) (shader-location = 5)
|
||||
float *normals; // Vertex normals (XYZ - 3 components per vertex) (shader-location = 2)
|
||||
float *tangents; // Vertex tangents (XYZ - 3 components per vertex) (shader-location = 4)
|
||||
unsigned char *colors; // Vertex colors (RGBA - 4 components per vertex) (shader-location = 3)
|
||||
unsigned short *indices;// Vertex indices (in case vertex data comes indexed)
|
||||
|
||||
unsigned int vaoId; // OpenGL Vertex Array Object id
|
||||
unsigned int vboId[7]; // OpenGL Vertex Buffer Objects id (7 types of vertex data)
|
||||
} Mesh;
|
||||
|
||||
// Shader type (generic shader)
|
||||
// Shader type (generic)
|
||||
typedef struct Shader {
|
||||
unsigned int id; // Shader program id
|
||||
|
||||
// Vertex attributes locations (default locations)
|
||||
int vertexLoc; // Vertex attribute location point (default-location = 0)
|
||||
int texcoordLoc; // Texcoord attribute location point (default-location = 1)
|
||||
int texcoord2Loc; // Texcoord2 attribute location point (default-location = 5)
|
||||
int normalLoc; // Normal attribute location point (default-location = 2)
|
||||
int tangentLoc; // Tangent attribute location point (default-location = 4)
|
||||
int colorLoc; // Color attibute location point (default-location = 3)
|
||||
|
||||
// Uniform locations
|
||||
int mvpLoc; // ModelView-Projection matrix uniform location point (vertex shader)
|
||||
int colDiffuseLoc; // Diffuse color uniform location point (fragment shader)
|
||||
int colAmbientLoc; // Ambient color uniform location point (fragment shader)
|
||||
int colSpecularLoc; // Specular color uniform location point (fragment shader)
|
||||
|
||||
// Texture map locations (generic for any kind of map)
|
||||
int mapTexture0Loc; // Map texture uniform location point (default-texture-unit = 0)
|
||||
int mapTexture1Loc; // Map texture uniform location point (default-texture-unit = 1)
|
||||
int mapTexture2Loc; // Map texture uniform location point (default-texture-unit = 2)
|
||||
unsigned int id; // Shader program id
|
||||
int locs[MAX_SHADER_LOCATIONS]; // Shader locations array
|
||||
} Shader;
|
||||
|
||||
// Material type
|
||||
// Material texture map
|
||||
typedef struct MaterialMap {
|
||||
Texture2D texture; // Material map texture
|
||||
Color color; // Material map color
|
||||
float value; // Material map value
|
||||
} MaterialMap;
|
||||
|
||||
// Material type (generic)
|
||||
typedef struct Material {
|
||||
Shader shader; // Standard shader (supports 3 map textures)
|
||||
|
||||
Texture2D texDiffuse; // Diffuse texture (binded to shader mapTexture0Loc)
|
||||
Texture2D texNormal; // Normal texture (binded to shader mapTexture1Loc)
|
||||
Texture2D texSpecular; // Specular texture (binded to shader mapTexture2Loc)
|
||||
|
||||
Color colDiffuse; // Diffuse color
|
||||
Color colAmbient; // Ambient color
|
||||
Color colSpecular; // Specular color
|
||||
|
||||
float glossiness; // Glossiness level (Ranges from 0 to 1000)
|
||||
Shader shader; // Material shader
|
||||
MaterialMap maps[MAX_MATERIAL_MAPS]; // Material maps
|
||||
float *params; // Material generic parameters (if required)
|
||||
} Material;
|
||||
|
||||
// Model type
|
||||
|
@ -475,12 +467,12 @@ typedef struct Ray {
|
|||
Vector3 direction; // Ray direction
|
||||
} Ray;
|
||||
|
||||
// Information returned from a raycast
|
||||
// Raycast hit information
|
||||
typedef struct RayHitInfo {
|
||||
bool hit; // Did the ray hit something?
|
||||
float distance; // Distance to nearest hit
|
||||
Vector3 hitPosition; // Position of nearest hit
|
||||
Vector3 hitNormal; // Surface normal of hit
|
||||
Vector3 position; // Position of nearest hit
|
||||
Vector3 normal; // Surface normal of hit
|
||||
} RayHitInfo;
|
||||
|
||||
// Wave type, defines audio wave data
|
||||
|
@ -531,18 +523,82 @@ typedef struct RRESData {
|
|||
// RRES type (pointer to RRESData array)
|
||||
typedef struct RRESData *RRES;
|
||||
|
||||
// Head-Mounted-Display device parameters
|
||||
typedef struct VrDeviceInfo {
|
||||
int hResolution; // HMD horizontal resolution in pixels
|
||||
int vResolution; // HMD vertical resolution in pixels
|
||||
float hScreenSize; // HMD horizontal size in meters
|
||||
float vScreenSize; // HMD vertical size in meters
|
||||
float vScreenCenter; // HMD screen center in meters
|
||||
float eyeToScreenDistance; // HMD distance between eye and display in meters
|
||||
float lensSeparationDistance; // HMD lens separation distance in meters
|
||||
float interpupillaryDistance; // HMD IPD (distance between pupils) in meters
|
||||
float lensDistortionValues[4]; // HMD lens distortion constant parameters
|
||||
float chromaAbCorrection[4]; // HMD chromatic aberration correction parameters
|
||||
} VrDeviceInfo;
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Enumerators Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
// Trace log type
|
||||
typedef enum {
|
||||
INFO = 0,
|
||||
WARNING,
|
||||
ERROR,
|
||||
DEBUG,
|
||||
OTHER
|
||||
LOG_INFO = 0,
|
||||
LOG_WARNING,
|
||||
LOG_ERROR,
|
||||
LOG_DEBUG,
|
||||
LOG_OTHER
|
||||
} LogType;
|
||||
|
||||
// Shader location point type
|
||||
typedef enum {
|
||||
LOC_VERTEX_POSITION = 0,
|
||||
LOC_VERTEX_TEXCOORD01,
|
||||
LOC_VERTEX_TEXCOORD02,
|
||||
LOC_VERTEX_NORMAL,
|
||||
LOC_VERTEX_TANGENT,
|
||||
LOC_VERTEX_COLOR,
|
||||
LOC_MATRIX_MVP,
|
||||
LOC_MATRIX_MODEL,
|
||||
LOC_MATRIX_VIEW,
|
||||
LOC_MATRIX_PROJECTION,
|
||||
LOC_VECTOR_VIEW,
|
||||
LOC_COLOR_DIFFUSE,
|
||||
LOC_COLOR_SPECULAR,
|
||||
LOC_COLOR_AMBIENT,
|
||||
LOC_MAP_ALBEDO, // LOC_MAP_DIFFUSE
|
||||
LOC_MAP_METALNESS, // LOC_MAP_SPECULAR
|
||||
LOC_MAP_NORMAL,
|
||||
LOC_MAP_ROUGHNESS,
|
||||
LOC_MAP_OCCUSION,
|
||||
LOC_MAP_EMISSION,
|
||||
LOC_MAP_HEIGHT,
|
||||
LOC_MAP_CUBEMAP,
|
||||
LOC_MAP_IRRADIANCE,
|
||||
LOC_MAP_PREFILTER,
|
||||
LOC_MAP_BRDF
|
||||
} ShaderLocationIndex;
|
||||
|
||||
#define LOC_MAP_DIFFUSE LOC_MAP_ALBEDO
|
||||
#define LOC_MAP_SPECULAR LOC_MAP_METALNESS
|
||||
|
||||
// Material map type
|
||||
typedef enum {
|
||||
MAP_ALBEDO = 0, // MAP_DIFFUSE
|
||||
MAP_METALNESS = 1, // MAP_SPECULAR
|
||||
MAP_NORMAL = 2,
|
||||
MAP_ROUGHNESS = 3,
|
||||
MAP_OCCLUSION,
|
||||
MAP_EMISSION,
|
||||
MAP_HEIGHT,
|
||||
MAP_CUBEMAP, // NOTE: Uses GL_TEXTURE_CUBE_MAP
|
||||
MAP_IRRADIANCE, // NOTE: Uses GL_TEXTURE_CUBE_MAP
|
||||
MAP_PREFILTER, // NOTE: Uses GL_TEXTURE_CUBE_MAP
|
||||
MAP_BRDF
|
||||
} TexmapIndex;
|
||||
|
||||
#define MAP_DIFFUSE MAP_ALBEDO
|
||||
#define MAP_SPECULAR MAP_METALNESS
|
||||
|
||||
// Texture formats
|
||||
// NOTE: Support depends on OpenGL version and platform
|
||||
typedef enum {
|
||||
|
@ -553,6 +609,7 @@ typedef enum {
|
|||
UNCOMPRESSED_R5G5B5A1, // 16 bpp (1 bit alpha)
|
||||
UNCOMPRESSED_R4G4B4A4, // 16 bpp (4 bit alpha)
|
||||
UNCOMPRESSED_R8G8B8A8, // 32 bpp
|
||||
UNCOMPRESSED_R32G32B32, // 32 bit per channel (float) - HDR
|
||||
COMPRESSED_DXT1_RGB, // 4 bpp (no alpha)
|
||||
COMPRESSED_DXT1_RGBA, // 4 bpp (1 bit alpha)
|
||||
COMPRESSED_DXT3_RGBA, // 8 bpp
|
||||
|
@ -622,13 +679,10 @@ typedef enum {
|
|||
HMD_DEFAULT_DEVICE = 0,
|
||||
HMD_OCULUS_RIFT_DK2,
|
||||
HMD_OCULUS_RIFT_CV1,
|
||||
HMD_OCULUS_GO,
|
||||
HMD_VALVE_HTC_VIVE,
|
||||
HMD_SAMSUNG_GEAR_VR,
|
||||
HMD_GOOGLE_CARDBOARD,
|
||||
HMD_SONY_PLAYSTATION_VR,
|
||||
HMD_RAZER_OSVR,
|
||||
HMD_FOVE_VR,
|
||||
} VrDevice;
|
||||
HMD_SONY_PSVR
|
||||
} VrDeviceType;
|
||||
|
||||
// RRESData type
|
||||
typedef enum {
|
||||
|
@ -654,74 +708,94 @@ extern "C" { // Prevents name mangling of functions
|
|||
//------------------------------------------------------------------------------------
|
||||
// Window and Graphics Device Functions (Module: core)
|
||||
//------------------------------------------------------------------------------------
|
||||
#if defined(PLATFORM_ANDROID)
|
||||
RLAPI void InitWindow(int width, int height, void *state); // Init Android Activity and OpenGL Graphics (struct android_app)
|
||||
#elif defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB)
|
||||
RLAPI void InitWindow(int width, int height, const char *title); // Initialize Window and OpenGL Graphics
|
||||
#endif
|
||||
|
||||
RLAPI void CloseWindow(void); // Close Window and Terminate Context
|
||||
RLAPI bool WindowShouldClose(void); // Detect if KEY_ESCAPE pressed or Close icon pressed
|
||||
RLAPI bool IsWindowMinimized(void); // Detect if window has been minimized (or lost focus)
|
||||
RLAPI void ToggleFullscreen(void); // Fullscreen toggle (only PLATFORM_DESKTOP)
|
||||
// Window-related functions
|
||||
#if defined(PLATFORM_ANDROID)
|
||||
RLAPI void InitWindow(int width, int height, void *state); // Initialize Android activity
|
||||
#elif defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB)
|
||||
RLAPI void InitWindow(int width, int height, const char *title); // Initialize window and OpenGL context
|
||||
#endif
|
||||
RLAPI void CloseWindow(void); // Close window and unload OpenGL context
|
||||
RLAPI bool WindowShouldClose(void); // Check if KEY_ESCAPE pressed or Close icon pressed
|
||||
RLAPI bool IsWindowMinimized(void); // Check if window has been minimized (or lost focus)
|
||||
RLAPI void ToggleFullscreen(void); // Toggle fullscreen mode (only PLATFORM_DESKTOP)
|
||||
RLAPI void SetWindowIcon(Image image); // Set icon for window (only PLATFORM_DESKTOP)
|
||||
RLAPI void SetWindowTitle(const char *title); // Set title for window (only PLATFORM_DESKTOP)
|
||||
RLAPI void SetWindowPosition(int x, int y); // Set window position on screen (only PLATFORM_DESKTOP)
|
||||
RLAPI void SetWindowMonitor(int monitor); // Set monitor for the current window (fullscreen mode)
|
||||
RLAPI void SetWindowMinSize(int width, int height); // Set window minimum dimensions (for FLAG_WINDOW_RESIZABLE)
|
||||
RLAPI int GetScreenWidth(void); // Get current screen width
|
||||
RLAPI int GetScreenHeight(void); // Get current screen height
|
||||
|
||||
#if !defined(PLATFORM_ANDROID)
|
||||
// Cursor-related functions
|
||||
RLAPI void ShowCursor(void); // Shows cursor
|
||||
RLAPI void HideCursor(void); // Hides cursor
|
||||
RLAPI bool IsCursorHidden(void); // Returns true if cursor is not visible
|
||||
RLAPI void EnableCursor(void); // Enables cursor
|
||||
RLAPI void DisableCursor(void); // Disables cursor
|
||||
RLAPI bool IsCursorHidden(void); // Check if cursor is not visible
|
||||
RLAPI void EnableCursor(void); // Enables cursor (unlock cursor)
|
||||
RLAPI void DisableCursor(void); // Disables cursor (lock cursor)
|
||||
#endif
|
||||
|
||||
RLAPI void ClearBackground(Color color); // Sets Background Color
|
||||
RLAPI void BeginDrawing(void); // Setup drawing canvas to start drawing
|
||||
RLAPI void EndDrawing(void); // End canvas drawing and Swap Buffers (Double Buffering)
|
||||
|
||||
RLAPI void Begin2dMode(Camera2D camera); // Initialize 2D mode with custom camera
|
||||
RLAPI void End2dMode(void); // Ends 2D mode custom camera usage
|
||||
RLAPI void Begin3dMode(Camera camera); // Initializes 3D mode for drawing (Camera setup)
|
||||
// Drawing-related functions
|
||||
RLAPI void ClearBackground(Color color); // Set background color (framebuffer clear color)
|
||||
RLAPI void BeginDrawing(void); // Setup canvas (framebuffer) to start drawing
|
||||
RLAPI void EndDrawing(void); // End canvas drawing and swap buffers (double buffering)
|
||||
RLAPI void Begin2dMode(Camera2D camera); // Initialize 2D mode with custom camera (2D)
|
||||
RLAPI void End2dMode(void); // Ends 2D mode with custom camera
|
||||
RLAPI void Begin3dMode(Camera camera); // Initializes 3D mode with custom camera (3D)
|
||||
RLAPI void End3dMode(void); // Ends 3D mode and returns to default 2D orthographic mode
|
||||
RLAPI void BeginTextureMode(RenderTexture2D target); // Initializes render texture for drawing
|
||||
RLAPI void EndTextureMode(void); // Ends drawing to render texture
|
||||
|
||||
// Screen-space-related functions
|
||||
RLAPI Ray GetMouseRay(Vector2 mousePosition, Camera camera); // Returns a ray trace from mouse position
|
||||
RLAPI Vector2 GetWorldToScreen(Vector3 position, Camera camera); // Returns the screen space position from a 3d world space position
|
||||
RLAPI Vector2 GetWorldToScreen(Vector3 position, Camera camera); // Returns the screen space position for a 3d world space position
|
||||
RLAPI Matrix GetCameraMatrix(Camera camera); // Returns camera transform matrix (view matrix)
|
||||
|
||||
// Timming-related functions
|
||||
RLAPI void SetTargetFPS(int fps); // Set target FPS (maximum)
|
||||
RLAPI int GetFPS(void); // Returns current FPS
|
||||
RLAPI float GetFrameTime(void); // Returns time in seconds for one frame
|
||||
RLAPI float GetFrameTime(void); // Returns time in seconds for last frame drawn
|
||||
|
||||
RLAPI Color GetColor(int hexValue); // Returns a Color struct from hexadecimal value
|
||||
// Color-related functions
|
||||
RLAPI int GetHexValue(Color color); // Returns hexadecimal value for a Color
|
||||
RLAPI float *ColorToFloat(Color color); // Converts Color to float array and normalizes
|
||||
RLAPI float *VectorToFloat(Vector3 vec); // Converts Vector3 to float array
|
||||
RLAPI float *MatrixToFloat(Matrix mat); // Converts Matrix to float array
|
||||
|
||||
RLAPI int GetRandomValue(int min, int max); // Returns a random value between min and max (both included)
|
||||
RLAPI Color GetColor(int hexValue); // Returns a Color struct from hexadecimal value
|
||||
RLAPI Color Fade(Color color, float alpha); // Color fade-in or fade-out, alpha goes from 0.0f to 1.0f
|
||||
RLAPI float *ColorToFloat(Color color); // Converts Color to float array and normalizes
|
||||
|
||||
RLAPI void ShowLogo(void); // Activates raylib logo at startup (can be done with flags)
|
||||
RLAPI void SetConfigFlags(char flags); // Setup some window configuration flags
|
||||
RLAPI void TraceLog(int logType, const char *text, ...); // Show trace log messages (INFO, WARNING, ERROR, DEBUG)
|
||||
RLAPI void TakeScreenshot(void); // Takes a screenshot and saves it in the same folder as executable
|
||||
// Math useful functions (available from raymath.h)
|
||||
RLAPI float *VectorToFloat(Vector3 vec); // Returns Vector3 as float array
|
||||
RLAPI float *MatrixToFloat(Matrix mat); // Returns Matrix as float array
|
||||
RLAPI Vector3 Vector3Zero(void); // Vector with components value 0.0f
|
||||
RLAPI Vector3 Vector3One(void); // Vector with components value 1.0f
|
||||
RLAPI Matrix MatrixIdentity(void); // Returns identity matrix
|
||||
|
||||
// Misc. functions
|
||||
RLAPI void ShowLogo(void); // Activate raylib logo at startup (can be done with flags)
|
||||
RLAPI void SetConfigFlags(char flags); // Setup window configuration flags (view FLAGS)
|
||||
RLAPI void TraceLog(int logType, const char *text, ...); // Show trace log messages (LOG_INFO, LOG_WARNING, LOG_ERROR, LOG_DEBUG)
|
||||
RLAPI void TakeScreenshot(const char *fileName); // Takes a screenshot of current screen (saved a .png)
|
||||
RLAPI int GetRandomValue(int min, int max); // Returns a random value between min and max (both included)
|
||||
|
||||
// Files management functions
|
||||
RLAPI bool IsFileExtension(const char *fileName, const char *ext);// Check file extension
|
||||
|
||||
RLAPI bool IsFileDropped(void); // Check if a file have been dropped into window
|
||||
RLAPI char **GetDroppedFiles(int *count); // Retrieve dropped files into window
|
||||
RLAPI const char *GetExtension(const char *fileName); // Get file extension
|
||||
RLAPI const char *GetDirectoryPath(const char *fileName); // Get directory for a given fileName (with path)
|
||||
RLAPI const char *GetWorkingDirectory(void); // Get current working directory
|
||||
RLAPI bool ChangeDirectory(const char *dir); // Change working directory, returns true if success
|
||||
RLAPI bool IsFileDropped(void); // Check if a file has been dropped into window
|
||||
RLAPI char **GetDroppedFiles(int *count); // Get dropped files names
|
||||
RLAPI void ClearDroppedFiles(void); // Clear dropped files paths buffer
|
||||
|
||||
RLAPI void StorageSaveValue(int position, int value); // Storage save integer value (to defined position)
|
||||
RLAPI int StorageLoadValue(int position); // Storage load integer value (from defined position)
|
||||
// Persistent storage management
|
||||
RLAPI void StorageSaveValue(int position, int value); // Save integer value to storage file (to defined position)
|
||||
RLAPI int StorageLoadValue(int position); // Load integer value from storage file (from defined position)
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Input Handling Functions (Module: core)
|
||||
//------------------------------------------------------------------------------------
|
||||
|
||||
// Input-related functions: keyboard
|
||||
RLAPI bool IsKeyPressed(int key); // Detect if a key has been pressed once
|
||||
RLAPI bool IsKeyDown(int key); // Detect if a key is being pressed
|
||||
RLAPI bool IsKeyReleased(int key); // Detect if a key has been released once
|
||||
|
@ -729,6 +803,7 @@ RLAPI bool IsKeyUp(int key); // Detect if a key
|
|||
RLAPI int GetKeyPressed(void); // Get latest key pressed
|
||||
RLAPI void SetExitKey(int key); // Set a custom key to exit program (default is ESC)
|
||||
|
||||
// Input-related functions: gamepads
|
||||
RLAPI bool IsGamepadAvailable(int gamepad); // Detect if a gamepad is available
|
||||
RLAPI bool IsGamepadName(int gamepad, const char *name); // Check gamepad name (if available)
|
||||
RLAPI const char *GetGamepadName(int gamepad); // Return gamepad internal name id
|
||||
|
@ -740,6 +815,7 @@ RLAPI int GetGamepadButtonPressed(void); // Get the last ga
|
|||
RLAPI int GetGamepadAxisCount(int gamepad); // Return gamepad axis count for a gamepad
|
||||
RLAPI float GetGamepadAxisMovement(int gamepad, int axis); // Return axis movement value for a gamepad axis
|
||||
|
||||
// Input-related functions: mouse
|
||||
RLAPI bool IsMouseButtonPressed(int button); // Detect if a mouse button has been pressed once
|
||||
RLAPI bool IsMouseButtonDown(int button); // Detect if a mouse button is being pressed
|
||||
RLAPI bool IsMouseButtonReleased(int button); // Detect if a mouse button has been released once
|
||||
|
@ -750,6 +826,7 @@ RLAPI Vector2 GetMousePosition(void); // Returns mouse p
|
|||
RLAPI void SetMousePosition(Vector2 position); // Set mouse position XY
|
||||
RLAPI int GetMouseWheelMove(void); // Returns mouse wheel movement Y
|
||||
|
||||
// Input-related functions: touch
|
||||
RLAPI int GetTouchX(void); // Returns touch position X for touch point 0 (relative to screen size)
|
||||
RLAPI int GetTouchY(void); // Returns touch position Y for touch point 0 (relative to screen size)
|
||||
RLAPI Vector2 GetTouchPosition(int index); // Returns touch position XY for a touch point index (relative to screen size)
|
||||
|
@ -783,6 +860,8 @@ RLAPI void SetCameraMoveControls(int frontKey, int backKey,
|
|||
//------------------------------------------------------------------------------------
|
||||
// Basic Shapes Drawing Functions (Module: shapes)
|
||||
//------------------------------------------------------------------------------------
|
||||
|
||||
// Basic shapes drawing functions
|
||||
RLAPI void DrawPixel(int posX, int posY, Color color); // Draw a pixel
|
||||
RLAPI void DrawPixelV(Vector2 position, Color color); // Draw a pixel (Vector version)
|
||||
RLAPI void DrawLine(int startPosX, int startPosY, int endPosX, int endPosY, Color color); // Draw a line
|
||||
|
@ -796,15 +875,19 @@ RLAPI void DrawCircleLines(int centerX, int centerY, float radius, Color color);
|
|||
RLAPI void DrawRectangle(int posX, int posY, int width, int height, Color color); // Draw a color-filled rectangle
|
||||
RLAPI void DrawRectangleRec(Rectangle rec, Color color); // Draw a color-filled rectangle
|
||||
RLAPI void DrawRectanglePro(Rectangle rec, Vector2 origin, float rotation, Color color); // Draw a color-filled rectangle with pro parameters
|
||||
RLAPI void DrawRectangleGradient(int posX, int posY, int width, int height, Color color1, Color color2); // Draw a gradient-filled rectangle
|
||||
RLAPI void DrawRectangleGradientV(int posX, int posY, int width, int height, Color color1, Color color2);// Draw a vertical-gradient-filled rectangle
|
||||
RLAPI void DrawRectangleGradientH(int posX, int posY, int width, int height, Color color1, Color color2);// Draw a horizontal-gradient-filled rectangle
|
||||
RLAPI void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3, Color col4); // Draw a gradient-filled rectangle with custom vertex colors
|
||||
RLAPI void DrawRectangleV(Vector2 position, Vector2 size, Color color); // Draw a color-filled rectangle (Vector version)
|
||||
RLAPI void DrawRectangleLines(int posX, int posY, int width, int height, Color color); // Draw rectangle outline
|
||||
RLAPI void DrawRectangleT(int posX, int posY, int width, int height, Color color); // Draw rectangle using text character
|
||||
RLAPI void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw a color-filled triangle
|
||||
RLAPI void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle outline
|
||||
RLAPI void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color color); // Draw a regular polygon (Vector version)
|
||||
RLAPI void DrawPolyEx(Vector2 *points, int numPoints, Color color); // Draw a closed polygon defined by points
|
||||
RLAPI void DrawPolyExLines(Vector2 *points, int numPoints, Color color); // Draw polygon lines
|
||||
|
||||
// Basic shapes collision detection functions
|
||||
RLAPI bool CheckCollisionRecs(Rectangle rec1, Rectangle rec2); // Check collision between two rectangles
|
||||
RLAPI bool CheckCollisionCircles(Vector2 center1, float radius1, Vector2 center2, float radius2); // Check collision between two circles
|
||||
RLAPI bool CheckCollisionCircleRec(Vector2 center, float radius, Rectangle rec); // Check collision between circle and rectangle
|
||||
|
@ -816,6 +899,8 @@ RLAPI bool CheckCollisionPointTriangle(Vector2 point, Vector2 p1, Vector2 p2, Ve
|
|||
//------------------------------------------------------------------------------------
|
||||
// Texture Loading and Drawing Functions (Module: textures)
|
||||
//------------------------------------------------------------------------------------
|
||||
|
||||
// Image/Texture2D data loading/unloading/saving functions
|
||||
RLAPI Image LoadImage(const char *fileName); // Load image from file into CPU memory (RAM)
|
||||
RLAPI Image LoadImageEx(Color *pixels, int width, int height); // Load image from Color array data (RGBA - 32bit)
|
||||
RLAPI Image LoadImagePro(void *data, int width, int height, int format); // Load image from raw data with parameters
|
||||
|
@ -829,6 +914,9 @@ RLAPI void UnloadRenderTexture(RenderTexture2D target);
|
|||
RLAPI Color *GetImageData(Image image); // Get pixel data from image as a Color struct array
|
||||
RLAPI Image GetTextureData(Texture2D texture); // Get pixel data from GPU texture and return an Image
|
||||
RLAPI void UpdateTexture(Texture2D texture, const void *pixels); // Update GPU texture with new data
|
||||
RLAPI void SaveImageAs(const char *fileName, Image image); // Save image to a PNG file
|
||||
|
||||
// Image manipulation functions
|
||||
RLAPI void ImageToPOT(Image *image, Color fillColor); // Convert image to POT (power-of-two)
|
||||
RLAPI void ImageFormat(Image *image, int newFormat); // Convert image data to desired format
|
||||
RLAPI void ImageAlphaMask(Image *image, Image alphaMask); // Apply alpha mask to image
|
||||
|
@ -850,10 +938,23 @@ RLAPI void ImageColorInvert(Image *image);
|
|||
RLAPI void ImageColorGrayscale(Image *image); // Modify image color: grayscale
|
||||
RLAPI void ImageColorContrast(Image *image, float contrast); // Modify image color: contrast (-100 to 100)
|
||||
RLAPI void ImageColorBrightness(Image *image, int brightness); // Modify image color: brightness (-255 to 255)
|
||||
|
||||
// Image generation functions
|
||||
RLAPI Image GenImageColor(int width, int height, Color color); // Generate image: plain color
|
||||
RLAPI Image GenImageGradientV(int width, int height, Color top, Color bottom); // Generate image: vertical gradient
|
||||
RLAPI Image GenImageGradientH(int width, int height, Color left, Color right); // Generate image: horizontal gradient
|
||||
RLAPI Image GenImageGradientRadial(int width, int height, float density, Color inner, Color outer); // Generate image: radial gradient
|
||||
RLAPI Image GenImageChecked(int width, int height, int checksX, int checksY, Color col1, Color col2); // Generate image: checked
|
||||
RLAPI Image GenImageWhiteNoise(int width, int height, float factor); // Generate image: white noise
|
||||
RLAPI Image GenImagePerlinNoise(int width, int height, float scale); // Generate image: perlin noise
|
||||
RLAPI Image GenImageCellular(int width, int height, int tileSize); // Generate image: cellular algorithm. Bigger tileSize means bigger cells
|
||||
|
||||
// Texture2D configuration functions
|
||||
RLAPI void GenTextureMipmaps(Texture2D *texture); // Generate GPU mipmaps for a texture
|
||||
RLAPI void SetTextureFilter(Texture2D texture, int filterMode); // Set texture scaling filter mode
|
||||
RLAPI void SetTextureWrap(Texture2D texture, int wrapMode); // Set texture wrapping mode
|
||||
|
||||
// Texture2D drawing functions
|
||||
RLAPI void DrawTexture(Texture2D texture, int posX, int posY, Color tint); // Draw a Texture2D
|
||||
RLAPI void DrawTextureV(Texture2D texture, Vector2 position, Color tint); // Draw a Texture2D with position defined as Vector2
|
||||
RLAPI void DrawTextureEx(Texture2D texture, Vector2 position, float rotation, float scale, Color tint); // Draw a Texture2D with extended parameters
|
||||
|
@ -864,24 +965,30 @@ RLAPI void DrawTexturePro(Texture2D texture, Rectangle sourceRec, Rectangle dest
|
|||
//------------------------------------------------------------------------------------
|
||||
// Font Loading and Text Drawing Functions (Module: text)
|
||||
//------------------------------------------------------------------------------------
|
||||
|
||||
// SpriteFont loading/unloading functions
|
||||
RLAPI SpriteFont GetDefaultFont(void); // Get the default SpriteFont
|
||||
RLAPI SpriteFont LoadSpriteFont(const char *fileName); // Load SpriteFont from file into GPU memory (VRAM)
|
||||
RLAPI SpriteFont LoadSpriteFontEx(const char *fileName, int fontSize, int charsCount, int *fontChars); // Load SpriteFont from file with extended parameters
|
||||
RLAPI void UnloadSpriteFont(SpriteFont spriteFont); // Unload SpriteFont from GPU memory (VRAM)
|
||||
|
||||
// Text drawing functions
|
||||
RLAPI void DrawFPS(int posX, int posY); // Shows current FPS
|
||||
RLAPI void DrawText(const char *text, int posX, int posY, int fontSize, Color color); // Draw text (using default font)
|
||||
RLAPI void DrawTextEx(SpriteFont spriteFont, const char* text, Vector2 position, // Draw text using SpriteFont and additional parameters
|
||||
float fontSize, int spacing, Color tint);
|
||||
|
||||
// Text misc. functions
|
||||
RLAPI int MeasureText(const char *text, int fontSize); // Measure string width for default font
|
||||
RLAPI Vector2 MeasureTextEx(SpriteFont spriteFont, const char *text, float fontSize, int spacing); // Measure string size for SpriteFont
|
||||
|
||||
RLAPI void DrawFPS(int posX, int posY); // Shows current FPS on top-left corner
|
||||
RLAPI const char *FormatText(const char *text, ...); // Formatting of text with variables to 'embed'
|
||||
RLAPI const char *SubText(const char *text, int position, int length); // Get a piece of a text string
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Basic 3d Shapes Drawing Functions (Module: models)
|
||||
//------------------------------------------------------------------------------------
|
||||
|
||||
// Basic geometric 3D shapes drawing functions
|
||||
RLAPI void DrawLine3D(Vector3 startPos, Vector3 endPos, Color color); // Draw a line in 3D world space
|
||||
RLAPI void DrawCircle3D(Vector3 center, float radius, Vector3 rotationAxis, float rotationAngle, Color color); // Draw a circle in 3D world space
|
||||
RLAPI void DrawCube(Vector3 position, float width, float height, float length, Color color); // Draw cube
|
||||
|
@ -902,19 +1009,33 @@ RLAPI void DrawGizmo(Vector3 position);
|
|||
//------------------------------------------------------------------------------------
|
||||
// Model 3d Loading and Drawing Functions (Module: models)
|
||||
//------------------------------------------------------------------------------------
|
||||
RLAPI Mesh LoadMesh(const char *fileName); // Load mesh from file
|
||||
RLAPI Mesh LoadMeshEx(int numVertex, float *vData, float *vtData, float *vnData, Color *cData); // Load mesh from vertex data
|
||||
RLAPI Model LoadModel(const char *fileName); // Load model from file
|
||||
RLAPI Model LoadModelFromMesh(Mesh data, bool dynamic); // Load model from mesh data
|
||||
RLAPI Model LoadHeightmap(Image heightmap, Vector3 size); // Load heightmap model from image data
|
||||
RLAPI Model LoadCubicmap(Image cubicmap); // Load cubes-based map model from image data
|
||||
RLAPI void UnloadMesh(Mesh *mesh); // Unload mesh from memory (RAM and/or VRAM)
|
||||
|
||||
// Model loading/unloading functions
|
||||
RLAPI Model LoadModel(const char *fileName); // Load model from files (mesh and material)
|
||||
RLAPI Model LoadModelFromMesh(Mesh mesh); // Load model from generated mesh
|
||||
RLAPI void UnloadModel(Model model); // Unload model from memory (RAM and/or VRAM)
|
||||
|
||||
// Mesh loading/unloading functions
|
||||
RLAPI Mesh LoadMesh(const char *fileName); // Load mesh from file
|
||||
RLAPI void UnloadMesh(Mesh *mesh); // Unload mesh from memory (RAM and/or VRAM)
|
||||
|
||||
// Mesh generation functions
|
||||
RLAPI Mesh GenMeshPlane(float width, float length, int resX, int resZ); // Generate plane mesh (with subdivisions)
|
||||
RLAPI Mesh GenMeshCube(float width, float height, float length); // Generate cuboid mesh
|
||||
RLAPI Mesh GenMeshSphere(float radius, int rings, int slices); // Generate sphere mesh (standard sphere)
|
||||
RLAPI Mesh GenMeshHemiSphere(float radius, int rings, int slices); // Generate half-sphere mesh (no bottom cap)
|
||||
RLAPI Mesh GenMeshCylinder(float radius, float height, int slices); // Generate cylinder mesh
|
||||
RLAPI Mesh GenMeshTorus(float radius, float size, int radSeg, int sides); // Generate torus mesh
|
||||
RLAPI Mesh GenMeshKnot(float radius, float size, int radSeg, int sides); // Generate trefoil knot mesh
|
||||
RLAPI Mesh GenMeshHeightmap(Image heightmap, Vector3 size); // Generate heightmap mesh from image data
|
||||
RLAPI Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize); // Generate cubes-based map mesh from image data
|
||||
|
||||
// Material loading/unloading functions
|
||||
RLAPI Material LoadMaterial(const char *fileName); // Load material from file
|
||||
RLAPI Material LoadDefaultMaterial(void); // Load default material (uses default models shader)
|
||||
RLAPI Material LoadMaterialDefault(void); // Load default material (Supports: DIFFUSE, SPECULAR, NORMAL maps)
|
||||
RLAPI void UnloadMaterial(Material material); // Unload material from GPU memory (VRAM)
|
||||
|
||||
// Model drawing functions
|
||||
RLAPI void DrawModel(Model model, Vector3 position, float scale, Color tint); // Draw a model (with texture if set)
|
||||
RLAPI void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis,
|
||||
float rotationAngle, Vector3 scale, Color tint); // Draw a model with extended parameters
|
||||
|
@ -922,11 +1043,11 @@ RLAPI void DrawModelWires(Model model, Vector3 position, float scale, Color tint
|
|||
RLAPI void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis,
|
||||
float rotationAngle, Vector3 scale, Color tint); // Draw a model wires (with texture if set) with extended parameters
|
||||
RLAPI void DrawBoundingBox(BoundingBox box, Color color); // Draw bounding box (wires)
|
||||
|
||||
RLAPI void DrawBillboard(Camera camera, Texture2D texture, Vector3 center, float size, Color tint); // Draw a billboard texture
|
||||
RLAPI void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle sourceRec,
|
||||
Vector3 center, float size, Color tint); // Draw a billboard texture defined by sourceRec
|
||||
|
||||
// Collision detection functions
|
||||
RLAPI BoundingBox CalculateBoundingBox(Mesh mesh); // Calculate mesh bounding box limits
|
||||
RLAPI bool CheckCollisionSpheres(Vector3 centerA, float radiusA, Vector3 centerB, float radiusB); // Detect collision between two spheres
|
||||
RLAPI bool CheckCollisionBoxes(BoundingBox box1, BoundingBox box2); // Detect collision between two bounding boxes
|
||||
|
@ -943,46 +1064,57 @@ RLAPI RayHitInfo GetCollisionRayGround(Ray ray, float groundHeight);
|
|||
// Shaders System Functions (Module: rlgl)
|
||||
// NOTE: This functions are useless when using OpenGL 1.1
|
||||
//------------------------------------------------------------------------------------
|
||||
|
||||
// Shader loading/unloading functions
|
||||
RLAPI char *LoadText(const char *fileName); // Load chars array from text file
|
||||
RLAPI Shader LoadShader(char *vsFileName, char *fsFileName); // Load shader from files and bind default locations
|
||||
RLAPI void UnloadShader(Shader shader); // Unload shader from GPU memory (VRAM)
|
||||
|
||||
RLAPI Shader GetDefaultShader(void); // Get default shader
|
||||
RLAPI Texture2D GetDefaultTexture(void); // Get default texture
|
||||
RLAPI Shader GetShaderDefault(void); // Get default shader
|
||||
RLAPI Texture2D GetTextureDefault(void); // Get default texture
|
||||
|
||||
// Shader configuration functions
|
||||
RLAPI int GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location
|
||||
RLAPI void SetShaderValue(Shader shader, int uniformLoc, float *value, int size); // Set shader uniform value (float)
|
||||
RLAPI void SetShaderValuei(Shader shader, int uniformLoc, int *value, int size); // Set shader uniform value (int)
|
||||
RLAPI void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat); // Set shader uniform value (matrix 4x4)
|
||||
|
||||
RLAPI void SetMatrixProjection(Matrix proj); // Set a custom projection matrix (replaces internal projection matrix)
|
||||
RLAPI void SetMatrixModelview(Matrix view); // Set a custom modelview matrix (replaces internal modelview matrix)
|
||||
|
||||
// Texture maps generation (PBR)
|
||||
// NOTE: Required shaders should be provided
|
||||
RLAPI Texture2D GenTextureCubemap(Shader shader, Texture2D skyHDR, int size); // Generate cubemap texture from HDR texture
|
||||
RLAPI Texture2D GenTextureIrradiance(Shader shader, Texture2D cubemap, int size); // Generate irradiance texture using cubemap data
|
||||
RLAPI Texture2D GenTexturePrefilter(Shader shader, Texture2D cubemap, int size); // Generate prefilter texture using cubemap data
|
||||
RLAPI Texture2D GenTextureBRDF(Shader shader, Texture2D cubemap, int size); // Generate BRDF texture using cubemap data
|
||||
|
||||
// Shading begin/end functions
|
||||
RLAPI void BeginShaderMode(Shader shader); // Begin custom shader drawing
|
||||
RLAPI void EndShaderMode(void); // End custom shader drawing (use default shader)
|
||||
RLAPI void BeginBlendMode(int mode); // Begin blending mode (alpha, additive, multiplied)
|
||||
RLAPI void EndBlendMode(void); // End blending mode (reset to default: alpha blending)
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// VR experience Functions (Module: rlgl)
|
||||
// NOTE: This functions are useless when using OpenGL 1.1
|
||||
//------------------------------------------------------------------------------------
|
||||
RLAPI void InitVrSimulator(int vrDevice); // Init VR simulator for selected device
|
||||
// VR control functions
|
||||
VrDeviceInfo GetVrDeviceInfo(int vrDeviceType); // Get VR device information for some standard devices
|
||||
void InitVrSimulator(VrDeviceInfo info); // Init VR simulator for selected device parameters
|
||||
RLAPI void CloseVrSimulator(void); // Close VR simulator for current device
|
||||
RLAPI bool IsVrSimulatorReady(void); // Detect if VR device is ready
|
||||
RLAPI bool IsVrSimulatorReady(void); // Detect if VR simulator is ready
|
||||
RLAPI void UpdateVrTracking(Camera *camera); // Update VR tracking (position and orientation) and camera
|
||||
RLAPI void ToggleVrMode(void); // Enable/Disable VR experience (device or simulator)
|
||||
RLAPI void ToggleVrMode(void); // Enable/Disable VR experience
|
||||
RLAPI void BeginVrDrawing(void); // Begin VR simulator stereo rendering
|
||||
RLAPI void EndVrDrawing(void); // End VR simulator stereo rendering
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Audio Loading and Playing Functions (Module: audio)
|
||||
//------------------------------------------------------------------------------------
|
||||
|
||||
// Audio device management functions
|
||||
RLAPI void InitAudioDevice(void); // Initialize audio device and context
|
||||
RLAPI void CloseAudioDevice(void); // Close the audio device and context
|
||||
RLAPI bool IsAudioDeviceReady(void); // Check if audio device has been initialized successfully
|
||||
RLAPI void SetMasterVolume(float volume); // Set master volume (listener)
|
||||
|
||||
// Wave/Sound loading/unloading functions
|
||||
RLAPI Wave LoadWave(const char *fileName); // Load wave data from file
|
||||
RLAPI Wave LoadWaveEx(void *data, int sampleCount, int sampleRate, int sampleSize, int channels); // Load wave data from raw array data
|
||||
RLAPI Sound LoadSound(const char *fileName); // Load sound from file
|
||||
|
@ -990,6 +1122,8 @@ RLAPI Sound LoadSoundFromWave(Wave wave); // Load so
|
|||
RLAPI void UpdateSound(Sound sound, const void *data, int samplesCount);// Update sound buffer with new data
|
||||
RLAPI void UnloadWave(Wave wave); // Unload wave data
|
||||
RLAPI void UnloadSound(Sound sound); // Unload sound
|
||||
|
||||
// Wave/Sound management functions
|
||||
RLAPI void PlaySound(Sound sound); // Play a sound
|
||||
RLAPI void PauseSound(Sound sound); // Pause a sound
|
||||
RLAPI void ResumeSound(Sound sound); // Resume a paused sound
|
||||
|
@ -1001,6 +1135,8 @@ RLAPI void WaveFormat(Wave *wave, int sampleRate, int sampleSize, int channels);
|
|||
RLAPI Wave WaveCopy(Wave wave); // Copy a wave to a new wave
|
||||
RLAPI void WaveCrop(Wave *wave, int initSample, int finalSample); // Crop a wave to defined samples range
|
||||
RLAPI float *GetWaveData(Wave wave); // Get samples data from wave as a floats array
|
||||
|
||||
// Music management functions
|
||||
RLAPI Music LoadMusicStream(const char *fileName); // Load music stream from file
|
||||
RLAPI void UnloadMusicStream(Music music); // Unload music stream
|
||||
RLAPI void PlayMusicStream(Music music); // Start music playing
|
||||
|
@ -1015,8 +1151,8 @@ RLAPI void SetMusicLoopCount(Music music, float count); // Set mus
|
|||
RLAPI float GetMusicTimeLength(Music music); // Get music time length (in seconds)
|
||||
RLAPI float GetMusicTimePlayed(Music music); // Get current music time played (in seconds)
|
||||
|
||||
RLAPI AudioStream InitAudioStream(unsigned int sampleRate,
|
||||
unsigned int sampleSize,
|
||||
// AudioStream management functions
|
||||
RLAPI AudioStream InitAudioStream(unsigned int sampleRate, unsigned int sampleSize,
|
||||
unsigned int channels); // Init audio stream (to stream raw audio pcm data)
|
||||
RLAPI void UpdateAudioStream(AudioStream stream, const void *data, int samplesCount); // Update audio stream buffers with data
|
||||
RLAPI void CloseAudioStream(AudioStream stream); // Close audio stream and free memory
|
||||
|
|
376
raylib/raymath.h
376
raylib/raymath.h
|
@ -1,6 +1,6 @@
|
|||
/**********************************************************************************************
|
||||
*
|
||||
* raymath v1.0 - Math functions to work with Vector3, Matrix and Quaternions
|
||||
* raymath v1.1 - Math functions to work with Vector3, Matrix and Quaternions
|
||||
*
|
||||
* CONFIGURATION:
|
||||
*
|
||||
|
@ -19,7 +19,7 @@
|
|||
*
|
||||
* LICENSE: zlib/libpng
|
||||
*
|
||||
* Copyright (c) 2015 Ramon Santamaria (@raysan5)
|
||||
* Copyright (c) 2015-2017 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* 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.
|
||||
|
@ -124,7 +124,7 @@ RMDEF Vector2 Vector2Zero(void); // Vector with c
|
|||
RMDEF Vector2 Vector2One(void); // Vector with components value 1.0f
|
||||
RMDEF Vector2 Vector2Add(Vector2 v1, Vector2 v2); // Add two vectors (v1 + v2)
|
||||
RMDEF Vector2 Vector2Subtract(Vector2 v1, Vector2 v2); // Subtract two vectors (v1 - v2)
|
||||
RMDEF float Vector2Lenght(Vector2 v); // Calculate vector lenght
|
||||
RMDEF float Vector2Length(Vector2 v); // Calculate vector length
|
||||
RMDEF float Vector2DotProduct(Vector2 v1, Vector2 v2); // Calculate two vectors dot product
|
||||
RMDEF float Vector2Distance(Vector2 v1, Vector2 v2); // Calculate distance between two vectors
|
||||
RMDEF float Vector2Angle(Vector2 v1, Vector2 v2); // Calculate angle between two vectors in X-axis
|
||||
|
@ -136,24 +136,27 @@ RMDEF void Vector2Normalize(Vector2 *v); // Normalize pro
|
|||
//------------------------------------------------------------------------------------
|
||||
// Functions Declaration to work with Vector3
|
||||
//------------------------------------------------------------------------------------
|
||||
RMDEF Vector3 VectorZero(void); // Vector with components value 0.0f
|
||||
RMDEF Vector3 VectorOne(void); // Vector with components value 1.0f
|
||||
RMDEF Vector3 VectorAdd(Vector3 v1, Vector3 v2); // Add two vectors
|
||||
RMDEF Vector3 VectorSubtract(Vector3 v1, Vector3 v2); // Substract two vectors
|
||||
RMDEF Vector3 VectorCrossProduct(Vector3 v1, Vector3 v2); // Calculate two vectors cross product
|
||||
RMDEF Vector3 VectorPerpendicular(Vector3 v); // Calculate one vector perpendicular vector
|
||||
RMDEF float VectorLength(const Vector3 v); // Calculate vector lenght
|
||||
RMDEF float VectorDotProduct(Vector3 v1, Vector3 v2); // Calculate two vectors dot product
|
||||
RMDEF float VectorDistance(Vector3 v1, Vector3 v2); // Calculate distance between two points
|
||||
RMDEF void VectorScale(Vector3 *v, float scale); // Scale provided vector
|
||||
RMDEF void VectorNegate(Vector3 *v); // Negate provided vector (invert direction)
|
||||
RMDEF void VectorNormalize(Vector3 *v); // Normalize provided vector
|
||||
RMDEF void VectorTransform(Vector3 *v, Matrix mat); // Transforms a Vector3 by a given Matrix
|
||||
RMDEF Vector3 VectorLerp(Vector3 v1, Vector3 v2, float amount); // Calculate linear interpolation between two vectors
|
||||
RMDEF Vector3 VectorReflect(Vector3 vector, Vector3 normal); // Calculate reflected vector to normal
|
||||
RMDEF Vector3 VectorMin(Vector3 vec1, Vector3 vec2); // Return min value for each pair of components
|
||||
RMDEF Vector3 VectorMax(Vector3 vec1, Vector3 vec2); // Return max value for each pair of components
|
||||
RMDEF Vector3 VectorBarycenter(Vector3 p, Vector3 a, Vector3 b, Vector3 c); // Barycenter coords for p in triangle abc
|
||||
RMDEF Vector3 Vector3Zero(void); // Vector with components value 0.0f
|
||||
RMDEF Vector3 Vector3One(void); // Vector with components value 1.0f
|
||||
RMDEF Vector3 Vector3Add(Vector3 v1, Vector3 v2); // Add two vectors
|
||||
RMDEF Vector3 Vector3Multiply(Vector3 v, float scalar); // Multiply vector by scalar
|
||||
RMDEF Vector3 Vector3MultiplyV(Vector3 v1, Vector3 v2); // Multiply vector by vector
|
||||
RMDEF Vector3 Vector3Subtract(Vector3 v1, Vector3 v2); // Substract two vectors
|
||||
RMDEF Vector3 Vector3CrossProduct(Vector3 v1, Vector3 v2); // Calculate two vectors cross product
|
||||
RMDEF Vector3 Vector3Perpendicular(Vector3 v); // Calculate one vector perpendicular vector
|
||||
RMDEF float Vector3Length(const Vector3 v); // Calculate vector length
|
||||
RMDEF float Vector3DotProduct(Vector3 v1, Vector3 v2); // Calculate two vectors dot product
|
||||
RMDEF float Vector3Distance(Vector3 v1, Vector3 v2); // Calculate distance between two points
|
||||
RMDEF void Vector3Scale(Vector3 *v, float scale); // Scale provided vector
|
||||
RMDEF void Vector3Negate(Vector3 *v); // Negate provided vector (invert direction)
|
||||
RMDEF void Vector3Normalize(Vector3 *v); // Normalize provided vector
|
||||
RMDEF void Vector3Transform(Vector3 *v, Matrix mat); // Transforms a Vector3 by a given Matrix
|
||||
RMDEF Vector3 Vector3Lerp(Vector3 v1, Vector3 v2, float amount); // Calculate linear interpolation between two vectors
|
||||
RMDEF Vector3 Vector3Reflect(Vector3 vector, Vector3 normal); // Calculate reflected vector to normal
|
||||
RMDEF Vector3 Vector3Min(Vector3 vec1, Vector3 vec2); // Return min value for each pair of components
|
||||
RMDEF Vector3 Vector3Max(Vector3 vec1, Vector3 vec2); // Return max value for each pair of components
|
||||
RMDEF Vector3 Vector3Barycenter(Vector3 p, Vector3 a, Vector3 b, Vector3 c); // Barycenter coords for p in triangle abc
|
||||
RMDEF float *Vector3ToFloat(Vector3 vec); // Returns Vector3 as float array
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Functions Declaration to work with Matrix
|
||||
|
@ -177,20 +180,27 @@ RMDEF Matrix MatrixFrustum(double left, double right, double bottom, double top,
|
|||
RMDEF Matrix MatrixPerspective(double fovy, double aspect, double near, double far); // Returns perspective projection matrix
|
||||
RMDEF Matrix MatrixOrtho(double left, double right, double bottom, double top, double near, double far); // Returns orthographic projection matrix
|
||||
RMDEF Matrix MatrixLookAt(Vector3 position, Vector3 target, Vector3 up); // Returns camera look-at matrix (view matrix)
|
||||
RMDEF float *MatrixToFloat(Matrix mat); // Returns float array of Matrix data
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Functions Declaration to work with Quaternions
|
||||
//------------------------------------------------------------------------------------
|
||||
RMDEF Quaternion QuaternionIdentity(void); // Returns identity quaternion
|
||||
RMDEF float QuaternionLength(Quaternion quat); // Compute the length of a quaternion
|
||||
RMDEF void QuaternionNormalize(Quaternion *q); // Normalize provided quaternion
|
||||
RMDEF void QuaternionInvert(Quaternion *quat); // Invert provided quaternion
|
||||
RMDEF Quaternion QuaternionMultiply(Quaternion q1, Quaternion q2); // Calculate two quaternion multiplication
|
||||
RMDEF Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float slerp); // Calculates spherical linear interpolation between two quaternions
|
||||
RMDEF Quaternion QuaternionLerp(Quaternion q1, Quaternion q2, float amount); // Calculate linear interpolation between two quaternions
|
||||
RMDEF Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float amount); // Calculates spherical linear interpolation between two quaternions
|
||||
RMDEF Quaternion QuaternionNlerp(Quaternion q1, Quaternion q2, float amount); // Calculate slerp-optimized interpolation between two quaternions
|
||||
RMDEF Quaternion QuaternionFromVector3ToVector3(Vector3 from, Vector3 to); // Calculate quaternion based on the rotation from one vector to another
|
||||
RMDEF Quaternion QuaternionFromMatrix(Matrix matrix); // Returns a quaternion for a given rotation matrix
|
||||
RMDEF Matrix QuaternionToMatrix(Quaternion q); // Returns a matrix for a given quaternion
|
||||
RMDEF Quaternion QuaternionFromAxisAngle(Vector3 axis, float angle); // Returns rotation quaternion for an angle and axis
|
||||
RMDEF void QuaternionToAxisAngle(Quaternion q, Vector3 *outAxis, float *outAngle); // Returns the rotation angle and axis for a given quaternion
|
||||
RMDEF void QuaternionTransform(Quaternion *q, Matrix mat); // Transform a quaternion given a transformation matrix
|
||||
RMDEF void QuaternionToAxisAngle(Quaternion q, Vector3 *outAxis, float *outAngle); // Returns the rotation angle and axis for a given quaternion
|
||||
RMDEF Quaternion QuaternionFromEuler(float roll, float pitch, float yaw); // Returns he quaternion equivalent to Euler angles
|
||||
RMDEF Vector3 QuaternionToEuler(Quaternion q); // Return the Euler angles equivalent to quaternion (roll, pitch, yaw)
|
||||
RMDEF void QuaternionTransform(Quaternion *q, Matrix mat); // Transform a quaternion given a transformation matrix
|
||||
|
||||
#endif // notdef RAYMATH_EXTERN_INLINE
|
||||
|
||||
|
@ -234,8 +244,8 @@ RMDEF Vector2 Vector2Subtract(Vector2 v1, Vector2 v2)
|
|||
return (Vector2){ v1.x - v2.x, v1.y - v2.y };
|
||||
}
|
||||
|
||||
// Calculate vector lenght
|
||||
RMDEF float Vector2Lenght(Vector2 v)
|
||||
// Calculate vector length
|
||||
RMDEF float Vector2Length(Vector2 v)
|
||||
{
|
||||
return sqrtf((v.x*v.x) + (v.y*v.y));
|
||||
}
|
||||
|
@ -285,7 +295,7 @@ RMDEF void Vector2Divide(Vector2 *v, float div)
|
|||
// Normalize provided vector
|
||||
RMDEF void Vector2Normalize(Vector2 *v)
|
||||
{
|
||||
Vector2Divide(v, Vector2Lenght(*v));
|
||||
Vector2Divide(v, Vector2Length(*v));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
|
@ -293,25 +303,47 @@ RMDEF void Vector2Normalize(Vector2 *v)
|
|||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Vector with components value 0.0f
|
||||
RMDEF Vector3 VectorZero(void) { return (Vector3){ 0.0f, 0.0f, 0.0f }; }
|
||||
RMDEF Vector3 Vector3Zero(void) { return (Vector3){ 0.0f, 0.0f, 0.0f }; }
|
||||
|
||||
// Vector with components value 1.0f
|
||||
RMDEF Vector3 VectorOne(void) { return (Vector3){ 1.0f, 1.0f, 1.0f }; }
|
||||
RMDEF Vector3 Vector3One(void) { return (Vector3){ 1.0f, 1.0f, 1.0f }; }
|
||||
|
||||
// Add two vectors
|
||||
RMDEF Vector3 VectorAdd(Vector3 v1, Vector3 v2)
|
||||
RMDEF Vector3 Vector3Add(Vector3 v1, Vector3 v2)
|
||||
{
|
||||
return (Vector3){ v1.x + v2.x, v1.y + v2.y, v1.z + v2.z };
|
||||
}
|
||||
|
||||
// Substract two vectors
|
||||
RMDEF Vector3 VectorSubtract(Vector3 v1, Vector3 v2)
|
||||
RMDEF Vector3 Vector3Subtract(Vector3 v1, Vector3 v2)
|
||||
{
|
||||
return (Vector3){ v1.x - v2.x, v1.y - v2.y, v1.z - v2.z };
|
||||
}
|
||||
|
||||
// Multiply vector by scalar
|
||||
RMDEF Vector3 Vector3Multiply(Vector3 v, float scalar)
|
||||
{
|
||||
v.x *= scalar;
|
||||
v.y *= scalar;
|
||||
v.z *= scalar;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
// Multiply vector by vector
|
||||
RMDEF Vector3 Vector3MultiplyV(Vector3 v1, Vector3 v2)
|
||||
{
|
||||
Vector3 result;
|
||||
|
||||
result.x = v1.x * v2.x;
|
||||
result.y = v1.y * v2.y;
|
||||
result.z = v1.z * v2.z;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Calculate two vectors cross product
|
||||
RMDEF Vector3 VectorCrossProduct(Vector3 v1, Vector3 v2)
|
||||
RMDEF Vector3 Vector3CrossProduct(Vector3 v1, Vector3 v2)
|
||||
{
|
||||
Vector3 result;
|
||||
|
||||
|
@ -323,7 +355,7 @@ RMDEF Vector3 VectorCrossProduct(Vector3 v1, Vector3 v2)
|
|||
}
|
||||
|
||||
// Calculate one vector perpendicular vector
|
||||
RMDEF Vector3 VectorPerpendicular(Vector3 v)
|
||||
RMDEF Vector3 Vector3Perpendicular(Vector3 v)
|
||||
{
|
||||
Vector3 result;
|
||||
|
||||
|
@ -341,25 +373,25 @@ RMDEF Vector3 VectorPerpendicular(Vector3 v)
|
|||
cardinalAxis = (Vector3){0.0f, 0.0f, 1.0f};
|
||||
}
|
||||
|
||||
result = VectorCrossProduct(v, cardinalAxis);
|
||||
result = Vector3CrossProduct(v, cardinalAxis);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Calculate vector lenght
|
||||
RMDEF float VectorLength(const Vector3 v)
|
||||
// Calculate vector length
|
||||
RMDEF float Vector3Length(const Vector3 v)
|
||||
{
|
||||
return sqrtf(v.x*v.x + v.y*v.y + v.z*v.z);
|
||||
}
|
||||
|
||||
// Calculate two vectors dot product
|
||||
RMDEF float VectorDotProduct(Vector3 v1, Vector3 v2)
|
||||
RMDEF float Vector3DotProduct(Vector3 v1, Vector3 v2)
|
||||
{
|
||||
return (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z);
|
||||
}
|
||||
|
||||
// Calculate distance between two vectors
|
||||
RMDEF float VectorDistance(Vector3 v1, Vector3 v2)
|
||||
RMDEF float Vector3Distance(Vector3 v1, Vector3 v2)
|
||||
{
|
||||
float dx = v2.x - v1.x;
|
||||
float dy = v2.y - v1.y;
|
||||
|
@ -369,7 +401,7 @@ RMDEF float VectorDistance(Vector3 v1, Vector3 v2)
|
|||
}
|
||||
|
||||
// Scale provided vector
|
||||
RMDEF void VectorScale(Vector3 *v, float scale)
|
||||
RMDEF void Vector3Scale(Vector3 *v, float scale)
|
||||
{
|
||||
v->x *= scale;
|
||||
v->y *= scale;
|
||||
|
@ -377,7 +409,7 @@ RMDEF void VectorScale(Vector3 *v, float scale)
|
|||
}
|
||||
|
||||
// Negate provided vector (invert direction)
|
||||
RMDEF void VectorNegate(Vector3 *v)
|
||||
RMDEF void Vector3Negate(Vector3 *v)
|
||||
{
|
||||
v->x = -v->x;
|
||||
v->y = -v->y;
|
||||
|
@ -385,11 +417,11 @@ RMDEF void VectorNegate(Vector3 *v)
|
|||
}
|
||||
|
||||
// Normalize provided vector
|
||||
RMDEF void VectorNormalize(Vector3 *v)
|
||||
RMDEF void Vector3Normalize(Vector3 *v)
|
||||
{
|
||||
float length, ilength;
|
||||
|
||||
length = VectorLength(*v);
|
||||
length = Vector3Length(*v);
|
||||
|
||||
if (length == 0.0f) length = 1.0f;
|
||||
|
||||
|
@ -401,8 +433,7 @@ RMDEF void VectorNormalize(Vector3 *v)
|
|||
}
|
||||
|
||||
// Transforms a Vector3 by a given Matrix
|
||||
// TODO: Review math (matrix transpose required?)
|
||||
RMDEF void VectorTransform(Vector3 *v, Matrix mat)
|
||||
RMDEF void Vector3Transform(Vector3 *v, Matrix mat)
|
||||
{
|
||||
float x = v->x;
|
||||
float y = v->y;
|
||||
|
@ -414,7 +445,7 @@ RMDEF void VectorTransform(Vector3 *v, Matrix mat)
|
|||
};
|
||||
|
||||
// Calculate linear interpolation between two vectors
|
||||
RMDEF Vector3 VectorLerp(Vector3 v1, Vector3 v2, float amount)
|
||||
RMDEF Vector3 Vector3Lerp(Vector3 v1, Vector3 v2, float amount)
|
||||
{
|
||||
Vector3 result;
|
||||
|
||||
|
@ -426,7 +457,7 @@ RMDEF Vector3 VectorLerp(Vector3 v1, Vector3 v2, float amount)
|
|||
}
|
||||
|
||||
// Calculate reflected vector to normal
|
||||
RMDEF Vector3 VectorReflect(Vector3 vector, Vector3 normal)
|
||||
RMDEF Vector3 Vector3Reflect(Vector3 vector, Vector3 normal)
|
||||
{
|
||||
// I is the original vector
|
||||
// N is the normal of the incident plane
|
||||
|
@ -434,7 +465,7 @@ RMDEF Vector3 VectorReflect(Vector3 vector, Vector3 normal)
|
|||
|
||||
Vector3 result;
|
||||
|
||||
float dotProduct = VectorDotProduct(vector, normal);
|
||||
float dotProduct = Vector3DotProduct(vector, normal);
|
||||
|
||||
result.x = vector.x - (2.0f*normal.x)*dotProduct;
|
||||
result.y = vector.y - (2.0f*normal.y)*dotProduct;
|
||||
|
@ -444,7 +475,7 @@ RMDEF Vector3 VectorReflect(Vector3 vector, Vector3 normal)
|
|||
}
|
||||
|
||||
// Return min value for each pair of components
|
||||
RMDEF Vector3 VectorMin(Vector3 vec1, Vector3 vec2)
|
||||
RMDEF Vector3 Vector3Min(Vector3 vec1, Vector3 vec2)
|
||||
{
|
||||
Vector3 result;
|
||||
|
||||
|
@ -456,7 +487,7 @@ RMDEF Vector3 VectorMin(Vector3 vec1, Vector3 vec2)
|
|||
}
|
||||
|
||||
// Return max value for each pair of components
|
||||
RMDEF Vector3 VectorMax(Vector3 vec1, Vector3 vec2)
|
||||
RMDEF Vector3 Vector3Max(Vector3 vec1, Vector3 vec2)
|
||||
{
|
||||
Vector3 result;
|
||||
|
||||
|
@ -469,18 +500,18 @@ RMDEF Vector3 VectorMax(Vector3 vec1, Vector3 vec2)
|
|||
|
||||
// Compute barycenter coordinates (u, v, w) for point p with respect to triangle (a, b, c)
|
||||
// NOTE: Assumes P is on the plane of the triangle
|
||||
RMDEF Vector3 VectorBarycenter(Vector3 p, Vector3 a, Vector3 b, Vector3 c)
|
||||
RMDEF Vector3 Vector3Barycenter(Vector3 p, Vector3 a, Vector3 b, Vector3 c)
|
||||
{
|
||||
//Vector v0 = b - a, v1 = c - a, v2 = p - a;
|
||||
|
||||
Vector3 v0 = VectorSubtract(b, a);
|
||||
Vector3 v1 = VectorSubtract(c, a);
|
||||
Vector3 v2 = VectorSubtract(p, a);
|
||||
float d00 = VectorDotProduct(v0, v0);
|
||||
float d01 = VectorDotProduct(v0, v1);
|
||||
float d11 = VectorDotProduct(v1, v1);
|
||||
float d20 = VectorDotProduct(v2, v0);
|
||||
float d21 = VectorDotProduct(v2, v1);
|
||||
Vector3 v0 = Vector3Subtract(b, a);
|
||||
Vector3 v1 = Vector3Subtract(c, a);
|
||||
Vector3 v2 = Vector3Subtract(p, a);
|
||||
float d00 = Vector3DotProduct(v0, v0);
|
||||
float d01 = Vector3DotProduct(v0, v1);
|
||||
float d11 = Vector3DotProduct(v1, v1);
|
||||
float d20 = Vector3DotProduct(v2, v0);
|
||||
float d21 = Vector3DotProduct(v2, v1);
|
||||
|
||||
float denom = d00*d11 - d01*d01;
|
||||
|
||||
|
@ -493,6 +524,18 @@ RMDEF Vector3 VectorBarycenter(Vector3 p, Vector3 a, Vector3 b, Vector3 c)
|
|||
return result;
|
||||
}
|
||||
|
||||
// Returns Vector3 as float array
|
||||
RMDEF float *Vector3ToFloat(Vector3 vec)
|
||||
{
|
||||
static float buffer[3];
|
||||
|
||||
buffer[0] = vec.x;
|
||||
buffer[1] = vec.y;
|
||||
buffer[2] = vec.z;
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module Functions Definition - Matrix math
|
||||
//----------------------------------------------------------------------------------
|
||||
|
@ -683,10 +726,10 @@ RMDEF Matrix MatrixSubstract(Matrix left, Matrix right)
|
|||
// Returns translation matrix
|
||||
RMDEF Matrix MatrixTranslate(float x, float y, float z)
|
||||
{
|
||||
Matrix result = { 1.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 1.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 1.0f, 0.0f,
|
||||
x, y, z, 1.0f };
|
||||
Matrix result = { 1.0f, 0.0f, 0.0f, x,
|
||||
0.0f, 1.0f, 0.0f, y,
|
||||
0.0f, 0.0f, 1.0f, z,
|
||||
0.0f, 0.0f, 0.0f, 1.0f };
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -811,22 +854,22 @@ RMDEF Matrix MatrixMultiply(Matrix left, Matrix right)
|
|||
{
|
||||
Matrix result;
|
||||
|
||||
result.m0 = right.m0*left.m0 + right.m1*left.m4 + right.m2*left.m8 + right.m3*left.m12;
|
||||
result.m1 = right.m0*left.m1 + right.m1*left.m5 + right.m2*left.m9 + right.m3*left.m13;
|
||||
result.m2 = right.m0*left.m2 + right.m1*left.m6 + right.m2*left.m10 + right.m3*left.m14;
|
||||
result.m3 = right.m0*left.m3 + right.m1*left.m7 + right.m2*left.m11 + right.m3*left.m15;
|
||||
result.m4 = right.m4*left.m0 + right.m5*left.m4 + right.m6*left.m8 + right.m7*left.m12;
|
||||
result.m5 = right.m4*left.m1 + right.m5*left.m5 + right.m6*left.m9 + right.m7*left.m13;
|
||||
result.m6 = right.m4*left.m2 + right.m5*left.m6 + right.m6*left.m10 + right.m7*left.m14;
|
||||
result.m7 = right.m4*left.m3 + right.m5*left.m7 + right.m6*left.m11 + right.m7*left.m15;
|
||||
result.m8 = right.m8*left.m0 + right.m9*left.m4 + right.m10*left.m8 + right.m11*left.m12;
|
||||
result.m9 = right.m8*left.m1 + right.m9*left.m5 + right.m10*left.m9 + right.m11*left.m13;
|
||||
result.m10 = right.m8*left.m2 + right.m9*left.m6 + right.m10*left.m10 + right.m11*left.m14;
|
||||
result.m11 = right.m8*left.m3 + right.m9*left.m7 + right.m10*left.m11 + right.m11*left.m15;
|
||||
result.m12 = right.m12*left.m0 + right.m13*left.m4 + right.m14*left.m8 + right.m15*left.m12;
|
||||
result.m13 = right.m12*left.m1 + right.m13*left.m5 + right.m14*left.m9 + right.m15*left.m13;
|
||||
result.m14 = right.m12*left.m2 + right.m13*left.m6 + right.m14*left.m10 + right.m15*left.m14;
|
||||
result.m15 = right.m12*left.m3 + right.m13*left.m7 + right.m14*left.m11 + right.m15*left.m15;
|
||||
result.m0 = left.m0*right.m0 + left.m1*right.m4 + left.m2*right.m8 + left.m3*right.m12;
|
||||
result.m1 = left.m0*right.m1 + left.m1*right.m5 + left.m2*right.m9 + left.m3*right.m13;
|
||||
result.m2 = left.m0*right.m2 + left.m1*right.m6 + left.m2*right.m10 + left.m3*right.m14;
|
||||
result.m3 = left.m0*right.m3 + left.m1*right.m7 + left.m2*right.m11 + left.m3*right.m15;
|
||||
result.m4 = left.m4*right.m0 + left.m5*right.m4 + left.m6*right.m8 + left.m7*right.m12;
|
||||
result.m5 = left.m4*right.m1 + left.m5*right.m5 + left.m6*right.m9 + left.m7*right.m13;
|
||||
result.m6 = left.m4*right.m2 + left.m5*right.m6 + left.m6*right.m10 + left.m7*right.m14;
|
||||
result.m7 = left.m4*right.m3 + left.m5*right.m7 + left.m6*right.m11 + left.m7*right.m15;
|
||||
result.m8 = left.m8*right.m0 + left.m9*right.m4 + left.m10*right.m8 + left.m11*right.m12;
|
||||
result.m9 = left.m8*right.m1 + left.m9*right.m5 + left.m10*right.m9 + left.m11*right.m13;
|
||||
result.m10 = left.m8*right.m2 + left.m9*right.m6 + left.m10*right.m10 + left.m11*right.m14;
|
||||
result.m11 = left.m8*right.m3 + left.m9*right.m7 + left.m10*right.m11 + left.m11*right.m15;
|
||||
result.m12 = left.m12*right.m0 + left.m13*right.m4 + left.m14*right.m8 + left.m15*right.m12;
|
||||
result.m13 = left.m12*right.m1 + left.m13*right.m5 + left.m14*right.m9 + left.m15*right.m13;
|
||||
result.m14 = left.m12*right.m2 + left.m13*right.m6 + left.m14*right.m10 + left.m15*right.m14;
|
||||
result.m15 = left.m12*right.m3 + left.m13*right.m7 + left.m14*right.m11 + left.m15*right.m15;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -864,9 +907,10 @@ RMDEF Matrix MatrixFrustum(double left, double right, double bottom, double top,
|
|||
}
|
||||
|
||||
// Returns perspective projection matrix
|
||||
// NOTE: Angle should be provided in radians
|
||||
RMDEF Matrix MatrixPerspective(double fovy, double aspect, double near, double far)
|
||||
{
|
||||
double top = near*tan(fovy*PI/360.0);
|
||||
double top = near*tan(fovy*0.5);
|
||||
double right = top*aspect;
|
||||
|
||||
return MatrixFrustum(-right, right, -top, top, near, far);
|
||||
|
@ -906,37 +950,70 @@ RMDEF Matrix MatrixLookAt(Vector3 eye, Vector3 target, Vector3 up)
|
|||
{
|
||||
Matrix result;
|
||||
|
||||
Vector3 z = VectorSubtract(eye, target);
|
||||
VectorNormalize(&z);
|
||||
Vector3 x = VectorCrossProduct(up, z);
|
||||
VectorNormalize(&x);
|
||||
Vector3 y = VectorCrossProduct(z, x);
|
||||
VectorNormalize(&y);
|
||||
|
||||
Vector3 z = Vector3Subtract(eye, target);
|
||||
Vector3Normalize(&z);
|
||||
Vector3 x = Vector3CrossProduct(up, z);
|
||||
Vector3Normalize(&x);
|
||||
Vector3 y = Vector3CrossProduct(z, x);
|
||||
Vector3Normalize(&y);
|
||||
|
||||
result.m0 = x.x;
|
||||
result.m1 = x.y;
|
||||
result.m2 = x.z;
|
||||
result.m3 = -((x.x*eye.x) + (x.y*eye.y) + (x.z*eye.z));
|
||||
result.m3 = 0.0f;
|
||||
result.m4 = y.x;
|
||||
result.m5 = y.y;
|
||||
result.m6 = y.z;
|
||||
result.m7 = -((y.x*eye.x) + (y.y*eye.y) + (y.z*eye.z));
|
||||
result.m7 = 0.0f;
|
||||
result.m8 = z.x;
|
||||
result.m9 = z.y;
|
||||
result.m10 = z.z;
|
||||
result.m11 = -((z.x*eye.x) + (z.y*eye.y) + (z.z*eye.z));
|
||||
result.m12 = 0.0f;
|
||||
result.m13 = 0.0f;
|
||||
result.m14 = 0.0f;
|
||||
result.m11 = 0.0f;
|
||||
result.m12 = eye.x;
|
||||
result.m13 = eye.y;
|
||||
result.m14 = eye.z;
|
||||
result.m15 = 1.0f;
|
||||
|
||||
MatrixInvert(&result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Returns float array of matrix data
|
||||
RMDEF float *MatrixToFloat(Matrix mat)
|
||||
{
|
||||
static float buffer[16];
|
||||
|
||||
buffer[0] = mat.m0;
|
||||
buffer[1] = mat.m1;
|
||||
buffer[2] = mat.m2;
|
||||
buffer[3] = mat.m3;
|
||||
buffer[4] = mat.m4;
|
||||
buffer[5] = mat.m5;
|
||||
buffer[6] = mat.m6;
|
||||
buffer[7] = mat.m7;
|
||||
buffer[8] = mat.m8;
|
||||
buffer[9] = mat.m9;
|
||||
buffer[10] = mat.m10;
|
||||
buffer[11] = mat.m11;
|
||||
buffer[12] = mat.m12;
|
||||
buffer[13] = mat.m13;
|
||||
buffer[14] = mat.m14;
|
||||
buffer[15] = mat.m15;
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module Functions Definition - Quaternion math
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Returns identity quaternion
|
||||
RMDEF Quaternion QuaternionIdentity(void)
|
||||
{
|
||||
return (Quaternion){ 0.0f, 0.0f, 0.0f, 1.0f };
|
||||
}
|
||||
|
||||
// Computes the length of a quaternion
|
||||
RMDEF float QuaternionLength(Quaternion quat)
|
||||
{
|
||||
|
@ -993,6 +1070,19 @@ RMDEF Quaternion QuaternionMultiply(Quaternion q1, Quaternion q2)
|
|||
return result;
|
||||
}
|
||||
|
||||
// Calculate linear interpolation between two quaternions
|
||||
RMDEF Quaternion QuaternionLerp(Quaternion q1, Quaternion q2, float amount)
|
||||
{
|
||||
Quaternion result;
|
||||
|
||||
result.x = q1.x + amount*(q2.x - q1.x);
|
||||
result.y = q1.y + amount*(q2.y - q1.y);
|
||||
result.z = q1.z + amount*(q2.z - q1.z);
|
||||
result.w = q1.w + amount*(q2.w - q1.w);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Calculates spherical linear interpolation between two quaternions
|
||||
RMDEF Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float amount)
|
||||
{
|
||||
|
@ -1001,6 +1091,7 @@ RMDEF Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float amount)
|
|||
float cosHalfTheta = q1.x*q2.x + q1.y*q2.y + q1.z*q2.z + q1.w*q2.w;
|
||||
|
||||
if (fabs(cosHalfTheta) >= 1.0f) result = q1;
|
||||
else if (cosHalfTheta > 0.95f) result = QuaternionNlerp(q1, q2, amount);
|
||||
else
|
||||
{
|
||||
float halfTheta = acos(cosHalfTheta);
|
||||
|
@ -1028,6 +1119,37 @@ RMDEF Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float amount)
|
|||
return result;
|
||||
}
|
||||
|
||||
// Calculate slerp-optimized interpolation between two quaternions
|
||||
RMDEF Quaternion QuaternionNlerp(Quaternion q1, Quaternion q2, float amount)
|
||||
{
|
||||
Quaternion result = QuaternionLerp(q1, q2, amount);
|
||||
QuaternionNormalize(&result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Calculate quaternion based on the rotation from one vector to another
|
||||
RMDEF Quaternion QuaternionFromVector3ToVector3(Vector3 from, Vector3 to)
|
||||
{
|
||||
Quaternion q = { 0 };
|
||||
|
||||
float cos2Theta = Vector3DotProduct(from, to);
|
||||
Vector3 cross = Vector3CrossProduct(from, to);
|
||||
|
||||
q.x = cross.x;
|
||||
q.y = cross.y;
|
||||
q.z = cross.y;
|
||||
q.w = 1.0f + cos2Theta; // NOTE: Added QuaternioIdentity()
|
||||
|
||||
// Normalize to essentially nlerp the original and identity to 0.5
|
||||
QuaternionNormalize(&q);
|
||||
|
||||
// Above lines are equivalent to:
|
||||
//Quaternion result = QuaternionNlerp(q, QuaternionIdentity(), 0.5f);
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
// Returns a quaternion for a given rotation matrix
|
||||
RMDEF Quaternion QuaternionFromMatrix(Matrix matrix)
|
||||
{
|
||||
|
@ -1094,18 +1216,21 @@ RMDEF Matrix QuaternionToMatrix(Quaternion q)
|
|||
float x2 = x + x;
|
||||
float y2 = y + y;
|
||||
float z2 = z + z;
|
||||
|
||||
float length = QuaternionLength(q);
|
||||
float lengthSquared = length*length;
|
||||
|
||||
float xx = x*x2;
|
||||
float xy = x*y2;
|
||||
float xz = x*z2;
|
||||
float xx = x*x2/lengthSquared;
|
||||
float xy = x*y2/lengthSquared;
|
||||
float xz = x*z2/lengthSquared;
|
||||
|
||||
float yy = y*y2;
|
||||
float yz = y*z2;
|
||||
float zz = z*z2;
|
||||
float yy = y*y2/lengthSquared;
|
||||
float yz = y*z2/lengthSquared;
|
||||
float zz = z*z2/lengthSquared;
|
||||
|
||||
float wx = w*x2;
|
||||
float wy = w*y2;
|
||||
float wz = w*z2;
|
||||
float wx = w*x2/lengthSquared;
|
||||
float wy = w*y2/lengthSquared;
|
||||
float wz = w*z2/lengthSquared;
|
||||
|
||||
result.m0 = 1.0f - (yy + zz);
|
||||
result.m1 = xy - wz;
|
||||
|
@ -1133,11 +1258,11 @@ RMDEF Quaternion QuaternionFromAxisAngle(Vector3 axis, float angle)
|
|||
{
|
||||
Quaternion result = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||
|
||||
if (VectorLength(axis) != 0.0f)
|
||||
if (Vector3Length(axis) != 0.0f)
|
||||
|
||||
angle *= 0.5f;
|
||||
|
||||
VectorNormalize(&axis);
|
||||
Vector3Normalize(&axis);
|
||||
|
||||
float sinres = sinf(angle);
|
||||
float cosres = cosf(angle);
|
||||
|
@ -1180,6 +1305,51 @@ RMDEF void QuaternionToAxisAngle(Quaternion q, Vector3 *outAxis, float *outAngle
|
|||
*outAngle = resAngle;
|
||||
}
|
||||
|
||||
// Returns he quaternion equivalent to Euler angles
|
||||
RMDEF Quaternion QuaternionFromEuler(float roll, float pitch, float yaw)
|
||||
{
|
||||
Quaternion q = { 0 };
|
||||
|
||||
float x0 = cosf(roll*0.5f);
|
||||
float x1 = sinf(roll*0.5f);
|
||||
float y0 = cosf(pitch*0.5f);
|
||||
float y1 = sinf(pitch*0.5f);
|
||||
float z0 = cosf(yaw*0.5f);
|
||||
float z1 = sinf(yaw*0.5f);
|
||||
|
||||
q.x = x1*y0*z0 - x0*y1*z1;
|
||||
q.y = x0*y1*z0 + x1*y0*z1;
|
||||
q.z = x0*y0*z1 - x1*y1*z0;
|
||||
q.w = x0*y0*z0 + x1*y1*z1;
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
// Return the Euler angles equivalent to quaternion (roll, pitch, yaw)
|
||||
// NOTE: Angles are returned in a Vector3 struct in degrees
|
||||
RMDEF Vector3 QuaternionToEuler(Quaternion q)
|
||||
{
|
||||
Vector3 v = { 0 };
|
||||
|
||||
// roll (x-axis rotation)
|
||||
float x0 = 2.0f*(q.w*q.x + q.y*q.z);
|
||||
float x1 = 1.0f - 2.0f*(q.x*q.x + q.y*q.y);
|
||||
v.x = atan2f(x0, x1)*RAD2DEG;
|
||||
|
||||
// pitch (y-axis rotation)
|
||||
float y0 = 2.0f*(q.w*q.y - q.z*q.x);
|
||||
y0 = y0 > 1.0f ? 1.0f : y0;
|
||||
y0 = y0 < -1.0f ? -1.0f : y0;
|
||||
v.y = asinf(y0)*RAD2DEG;
|
||||
|
||||
// yaw (z-axis rotation)
|
||||
float z0 = 2.0f*(q.w*q.z + q.x*q.y);
|
||||
float z1 = 1.0f - 2.0f*(q.y*q.y + q.z*q.z);
|
||||
v.z = atan2f(z0, z1)*RAD2DEG;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
// Transform a quaternion given a transformation matrix
|
||||
RMDEF void QuaternionTransform(Quaternion *q, Matrix mat)
|
||||
{
|
||||
|
|
1609
raylib/rlgl.c
1609
raylib/rlgl.c
File diff suppressed because it is too large
Load diff
371
raylib/rlgl.h
371
raylib/rlgl.h
|
@ -17,7 +17,9 @@
|
|||
* #define GRAPHICS_API_OPENGL_21
|
||||
* #define GRAPHICS_API_OPENGL_33
|
||||
* #define GRAPHICS_API_OPENGL_ES2
|
||||
* Use selected OpenGL backend
|
||||
* Use selected OpenGL graphics backend, should be supported by platform
|
||||
* Those preprocessor defines are only used on rlgl module, if OpenGL version is
|
||||
* required by any other module, use rlGetVersion() tocheck it
|
||||
*
|
||||
* #define RLGL_STANDALONE
|
||||
* Use rlgl as standalone library (no raylib dependency)
|
||||
|
@ -25,7 +27,7 @@
|
|||
* #define SUPPORT_VR_SIMULATION / SUPPORT_STEREO_RENDERING
|
||||
* Support VR simulation functionality (stereo rendering)
|
||||
*
|
||||
* #define SUPPORT_SHADER_DISTORTION
|
||||
* #define SUPPORT_DISTORTION_SHADER
|
||||
* Include stereo rendering distortion shader (shader_distortion.h)
|
||||
*
|
||||
* DEPENDENCIES:
|
||||
|
@ -35,7 +37,7 @@
|
|||
*
|
||||
* LICENSE: zlib/libpng
|
||||
*
|
||||
* Copyright (c) 2014-2016 Ramon Santamaria (@raysan5)
|
||||
* Copyright (c) 2014-2017 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* 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.
|
||||
|
@ -57,28 +59,14 @@
|
|||
#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: Model, Shader, Texture2D
|
||||
#include "utils.h" // Required for: TraceLog()
|
||||
#endif
|
||||
|
||||
#ifdef RLGL_STANDALONE
|
||||
#if defined(RLGL_STANDALONE)
|
||||
#define RAYMATH_STANDALONE
|
||||
#else
|
||||
#include "raylib.h" // Required for: Model, Shader, Texture2D, TraceLog()
|
||||
#endif
|
||||
|
||||
#include "raymath.h" // Required for: Vector3, Matrix
|
||||
|
||||
// Select desired OpenGL version
|
||||
// NOTE: Those preprocessor defines are only used on rlgl module,
|
||||
// if OpenGL version is required by any other module, it uses rlGetVersion()
|
||||
|
||||
// Choose opengl version here or just define it at compile time: -DGRAPHICS_API_OPENGL_33
|
||||
//#define GRAPHICS_API_OPENGL_11 // Only available on PLATFORM_DESKTOP
|
||||
//#define GRAPHICS_API_OPENGL_33 // Only available on PLATFORM_DESKTOP and RLGL_OCULUS_SUPPORT
|
||||
//#define GRAPHICS_API_OPENGL_ES2 // Only available on PLATFORM_ANDROID or PLATFORM_RPI or PLATFORM_WEB
|
||||
|
||||
// Security check in case no GRAPHICS_API_OPENGL_* defined
|
||||
#if !defined(GRAPHICS_API_OPENGL_11) && !defined(GRAPHICS_API_OPENGL_21) && !defined(GRAPHICS_API_OPENGL_33) && !defined(GRAPHICS_API_OPENGL_ES2)
|
||||
#define GRAPHICS_API_OPENGL_11
|
||||
|
@ -157,6 +145,56 @@ typedef unsigned char byte;
|
|||
// Boolean type
|
||||
typedef enum { false, true } bool;
|
||||
#endif
|
||||
|
||||
// Shader location point type
|
||||
typedef enum {
|
||||
LOC_VERTEX_POSITION = 0,
|
||||
LOC_VERTEX_TEXCOORD01,
|
||||
LOC_VERTEX_TEXCOORD02,
|
||||
LOC_VERTEX_NORMAL,
|
||||
LOC_VERTEX_TANGENT,
|
||||
LOC_VERTEX_COLOR,
|
||||
LOC_MATRIX_MVP,
|
||||
LOC_MATRIX_MODEL,
|
||||
LOC_MATRIX_VIEW,
|
||||
LOC_MATRIX_PROJECTION,
|
||||
LOC_VECTOR_VIEW,
|
||||
LOC_COLOR_DIFFUSE,
|
||||
LOC_COLOR_SPECULAR,
|
||||
LOC_COLOR_AMBIENT,
|
||||
LOC_MAP_ALBEDO, // LOC_MAP_DIFFUSE
|
||||
LOC_MAP_METALNESS, // LOC_MAP_SPECULAR
|
||||
LOC_MAP_NORMAL,
|
||||
LOC_MAP_ROUGHNESS,
|
||||
LOC_MAP_OCCUSION,
|
||||
LOC_MAP_EMISSION,
|
||||
LOC_MAP_HEIGHT,
|
||||
LOC_MAP_CUBEMAP,
|
||||
LOC_MAP_IRRADIANCE,
|
||||
LOC_MAP_PREFILTER,
|
||||
LOC_MAP_BRDF
|
||||
} ShaderLocationIndex;
|
||||
|
||||
#define LOC_MAP_DIFFUSE LOC_MAP_ALBEDO
|
||||
#define LOC_MAP_SPECULAR LOC_MAP_METALNESS
|
||||
|
||||
// Material map type
|
||||
typedef enum {
|
||||
MAP_ALBEDO = 0, // MAP_DIFFUSE
|
||||
MAP_METALNESS = 1, // MAP_SPECULAR
|
||||
MAP_NORMAL = 2,
|
||||
MAP_ROUGHNESS = 3,
|
||||
MAP_OCCLUSION,
|
||||
MAP_EMISSION,
|
||||
MAP_HEIGHT,
|
||||
MAP_CUBEMAP, // NOTE: Uses GL_TEXTURE_CUBE_MAP
|
||||
MAP_IRRADIANCE, // NOTE: Uses GL_TEXTURE_CUBE_MAP
|
||||
MAP_PREFILTER, // NOTE: Uses GL_TEXTURE_CUBE_MAP
|
||||
MAP_BRDF
|
||||
} TexmapIndex;
|
||||
|
||||
#define MAP_DIFFUSE MAP_ALBEDO
|
||||
#define MAP_SPECULAR MAP_METALNESS
|
||||
|
||||
// Color type, RGBA (32bit)
|
||||
typedef struct Color {
|
||||
|
@ -165,69 +203,7 @@ typedef unsigned char byte;
|
|||
unsigned char b;
|
||||
unsigned char a;
|
||||
} Color;
|
||||
|
||||
// Texture formats (support depends on OpenGL version)
|
||||
typedef enum {
|
||||
UNCOMPRESSED_GRAYSCALE = 1, // 8 bit per pixel (no alpha)
|
||||
UNCOMPRESSED_GRAY_ALPHA,
|
||||
UNCOMPRESSED_R5G6B5, // 16 bpp
|
||||
UNCOMPRESSED_R8G8B8, // 24 bpp
|
||||
UNCOMPRESSED_R5G5B5A1, // 16 bpp (1 bit alpha)
|
||||
UNCOMPRESSED_R4G4B4A4, // 16 bpp (4 bit alpha)
|
||||
UNCOMPRESSED_R8G8B8A8, // 32 bpp
|
||||
COMPRESSED_DXT1_RGB, // 4 bpp (no alpha)
|
||||
COMPRESSED_DXT1_RGBA, // 4 bpp (1 bit alpha)
|
||||
COMPRESSED_DXT3_RGBA, // 8 bpp
|
||||
COMPRESSED_DXT5_RGBA, // 8 bpp
|
||||
COMPRESSED_ETC1_RGB, // 4 bpp
|
||||
COMPRESSED_ETC2_RGB, // 4 bpp
|
||||
COMPRESSED_ETC2_EAC_RGBA, // 8 bpp
|
||||
COMPRESSED_PVRT_RGB, // 4 bpp
|
||||
COMPRESSED_PVRT_RGBA, // 4 bpp
|
||||
COMPRESSED_ASTC_4x4_RGBA, // 8 bpp
|
||||
COMPRESSED_ASTC_8x8_RGBA // 2 bpp
|
||||
} TextureFormat;
|
||||
|
||||
// Vertex data definning a mesh
|
||||
typedef struct Mesh {
|
||||
int vertexCount; // number of vertices stored in arrays
|
||||
int triangleCount; // number of triangles stored (indexed or not)
|
||||
float *vertices; // vertex position (XYZ - 3 components per vertex) (shader-location = 0)
|
||||
float *texcoords; // vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1)
|
||||
float *texcoords2; // vertex second texture coordinates (useful for lightmaps) (shader-location = 5)
|
||||
float *normals; // vertex normals (XYZ - 3 components per vertex) (shader-location = 2)
|
||||
float *tangents; // vertex tangents (XYZ - 3 components per vertex) (shader-location = 4)
|
||||
unsigned char *colors; // vertex colors (RGBA - 4 components per vertex) (shader-location = 3)
|
||||
unsigned short *indices;// vertex indices (in case vertex data comes indexed)
|
||||
|
||||
unsigned int vaoId; // OpenGL Vertex Array Object id
|
||||
unsigned int vboId[7]; // OpenGL Vertex Buffer Objects id (7 types of vertex data)
|
||||
} Mesh;
|
||||
|
||||
// Shader type (generic shader)
|
||||
typedef struct Shader {
|
||||
unsigned int id; // Shader program id
|
||||
|
||||
// Vertex attributes locations (default locations)
|
||||
int vertexLoc; // Vertex attribute location point (default-location = 0)
|
||||
int texcoordLoc; // Texcoord attribute location point (default-location = 1)
|
||||
int normalLoc; // Normal attribute location point (default-location = 2)
|
||||
int colorLoc; // Color attibute location point (default-location = 3)
|
||||
int tangentLoc; // Tangent attribute location point (default-location = 4)
|
||||
int texcoord2Loc; // Texcoord2 attribute location point (default-location = 5)
|
||||
|
||||
// Uniform locations
|
||||
int mvpLoc; // ModelView-Projection matrix uniform location point (vertex shader)
|
||||
int colDiffuseLoc; // Color uniform location point (fragment shader)
|
||||
int colAmbientLoc; // Ambient color uniform location point (fragment shader)
|
||||
int colSpecularLoc; // Specular color uniform location point (fragment shader)
|
||||
|
||||
// Texture map locations (generic for any kind of map)
|
||||
int mapTexture0Loc; // Map texture uniform location point (default-texture-unit = 0)
|
||||
int mapTexture1Loc; // Map texture uniform location point (default-texture-unit = 1)
|
||||
int mapTexture2Loc; // Map texture uniform location point (default-texture-unit = 2)
|
||||
} Shader;
|
||||
|
||||
|
||||
// Texture2D type
|
||||
// NOTE: Data stored in GPU memory
|
||||
typedef struct Texture2D {
|
||||
|
@ -245,19 +221,44 @@ typedef unsigned char byte;
|
|||
Texture2D depth; // Depth buffer attachment texture
|
||||
} RenderTexture2D;
|
||||
|
||||
// Material type
|
||||
// Vertex data definning a mesh
|
||||
typedef struct Mesh {
|
||||
int vertexCount; // number of vertices stored in arrays
|
||||
int triangleCount; // number of triangles stored (indexed or not)
|
||||
float *vertices; // vertex position (XYZ - 3 components per vertex) (shader-location = 0)
|
||||
float *texcoords; // vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1)
|
||||
float *texcoords2; // vertex second texture coordinates (useful for lightmaps) (shader-location = 5)
|
||||
float *normals; // vertex normals (XYZ - 3 components per vertex) (shader-location = 2)
|
||||
float *tangents; // vertex tangents (XYZ - 3 components per vertex) (shader-location = 4)
|
||||
unsigned char *colors; // vertex colors (RGBA - 4 components per vertex) (shader-location = 3)
|
||||
unsigned short *indices;// vertex indices (in case vertex data comes indexed)
|
||||
|
||||
unsigned int vaoId; // OpenGL Vertex Array Object id
|
||||
unsigned int vboId[7]; // OpenGL Vertex Buffer Objects id (7 types of vertex data)
|
||||
} Mesh;
|
||||
|
||||
// Shader and material limits
|
||||
#define MAX_SHADER_LOCATIONS 32
|
||||
#define MAX_MATERIAL_MAPS 12
|
||||
|
||||
// Shader type (generic)
|
||||
typedef struct Shader {
|
||||
unsigned int id; // Shader program id
|
||||
int locs[MAX_SHADER_LOCATIONS]; // Shader locations array
|
||||
} Shader;
|
||||
|
||||
// Material texture map
|
||||
typedef struct MaterialMap {
|
||||
Texture2D texture; // Material map texture
|
||||
Color color; // Material map color
|
||||
float value; // Material map value
|
||||
} MaterialMap;
|
||||
|
||||
// Material type (generic)
|
||||
typedef struct Material {
|
||||
Shader shader; // Standard shader (supports 3 map types: diffuse, normal, specular)
|
||||
|
||||
Texture2D texDiffuse; // Diffuse texture
|
||||
Texture2D texNormal; // Normal texture
|
||||
Texture2D texSpecular; // Specular texture
|
||||
|
||||
Color colDiffuse; // Diffuse color
|
||||
Color colAmbient; // Ambient color
|
||||
Color colSpecular; // Specular color
|
||||
|
||||
float glossiness; // Glossiness level (Ranges from 0 to 1000)
|
||||
Shader shader; // Material shader
|
||||
MaterialMap maps[MAX_MATERIAL_MAPS]; // Material maps
|
||||
float *params; // Material generic parameters (if required)
|
||||
} Material;
|
||||
|
||||
// Camera type, defines a camera position/orientation in 3d space
|
||||
|
@ -267,6 +268,52 @@ typedef unsigned char byte;
|
|||
Vector3 up; // Camera up vector (rotation over its axis)
|
||||
float fovy; // Camera field-of-view apperture in Y (degrees)
|
||||
} Camera;
|
||||
|
||||
// Head-Mounted-Display device parameters
|
||||
typedef struct VrDeviceInfo {
|
||||
int hResolution; // HMD horizontal resolution in pixels
|
||||
int vResolution; // HMD vertical resolution in pixels
|
||||
float hScreenSize; // HMD horizontal size in meters
|
||||
float vScreenSize; // HMD vertical size in meters
|
||||
float vScreenCenter; // HMD screen center in meters
|
||||
float eyeToScreenDistance; // HMD distance between eye and display in meters
|
||||
float lensSeparationDistance; // HMD lens separation distance in meters
|
||||
float interpupillaryDistance; // HMD IPD (distance between pupils) in meters
|
||||
float lensDistortionValues[4]; // HMD lens distortion constant parameters
|
||||
float chromaAbCorrection[4]; // HMD chromatic aberration correction parameters
|
||||
} VrDeviceInfo;
|
||||
|
||||
// TraceLog message types
|
||||
typedef enum {
|
||||
LOG_INFO = 0,
|
||||
LOG_ERROR,
|
||||
LOG_WARNING,
|
||||
LOG_DEBUG,
|
||||
LOG_OTHER
|
||||
} TraceLogType;
|
||||
|
||||
// Texture formats (support depends on OpenGL version)
|
||||
typedef enum {
|
||||
UNCOMPRESSED_GRAYSCALE = 1, // 8 bit per pixel (no alpha)
|
||||
UNCOMPRESSED_GRAY_ALPHA,
|
||||
UNCOMPRESSED_R5G6B5, // 16 bpp
|
||||
UNCOMPRESSED_R8G8B8, // 24 bpp
|
||||
UNCOMPRESSED_R5G5B5A1, // 16 bpp (1 bit alpha)
|
||||
UNCOMPRESSED_R4G4B4A4, // 16 bpp (4 bit alpha)
|
||||
UNCOMPRESSED_R8G8B8A8, // 32 bpp
|
||||
UNCOMPRESSED_R32G32B32, // 32 bit per channel (float) - HDR
|
||||
COMPRESSED_DXT1_RGB, // 4 bpp (no alpha)
|
||||
COMPRESSED_DXT1_RGBA, // 4 bpp (1 bit alpha)
|
||||
COMPRESSED_DXT3_RGBA, // 8 bpp
|
||||
COMPRESSED_DXT5_RGBA, // 8 bpp
|
||||
COMPRESSED_ETC1_RGB, // 4 bpp
|
||||
COMPRESSED_ETC2_RGB, // 4 bpp
|
||||
COMPRESSED_ETC2_EAC_RGBA, // 8 bpp
|
||||
COMPRESSED_PVRT_RGB, // 4 bpp
|
||||
COMPRESSED_PVRT_RGBA, // 4 bpp
|
||||
COMPRESSED_ASTC_4x4_RGBA, // 8 bpp
|
||||
COMPRESSED_ASTC_8x8_RGBA // 2 bpp
|
||||
} TextureFormat;
|
||||
|
||||
// Texture parameters: filter mode
|
||||
// NOTE 1: Filtering considers mipmaps if available in the texture
|
||||
|
@ -281,25 +328,27 @@ typedef unsigned char byte;
|
|||
} TextureFilterMode;
|
||||
|
||||
// Texture parameters: wrap mode
|
||||
typedef enum { WRAP_REPEAT = 0, WRAP_CLAMP, WRAP_MIRROR } TextureWrapMode;
|
||||
typedef enum {
|
||||
WRAP_REPEAT = 0,
|
||||
WRAP_CLAMP,
|
||||
WRAP_MIRROR
|
||||
} TextureWrapMode;
|
||||
|
||||
// Color blending modes (pre-defined)
|
||||
typedef enum { BLEND_ALPHA = 0, BLEND_ADDITIVE, BLEND_MULTIPLIED } BlendMode;
|
||||
|
||||
// TraceLog message types
|
||||
typedef enum { INFO = 0, ERROR, WARNING, DEBUG, OTHER } TraceLogType;
|
||||
typedef enum {
|
||||
BLEND_ALPHA = 0,
|
||||
BLEND_ADDITIVE,
|
||||
BLEND_MULTIPLIED
|
||||
} BlendMode;
|
||||
|
||||
// VR Head Mounted Display devices
|
||||
typedef enum {
|
||||
HMD_DEFAULT_DEVICE = 0,
|
||||
HMD_OCULUS_RIFT_DK2,
|
||||
HMD_OCULUS_RIFT_CV1,
|
||||
HMD_OCULUS_GO,
|
||||
HMD_VALVE_HTC_VIVE,
|
||||
HMD_SAMSUNG_GEAR_VR,
|
||||
HMD_GOOGLE_CARDBOARD,
|
||||
HMD_SONY_PLAYSTATION_VR,
|
||||
HMD_RAZER_OSVR,
|
||||
HMD_FOVE_VR,
|
||||
HMD_SONY_PSVR
|
||||
} VrDevice;
|
||||
#endif
|
||||
|
||||
|
@ -317,7 +366,7 @@ void rlLoadIdentity(void); // Reset current matrix to ident
|
|||
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 rlMultMatrixf(float *matf); // 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);
|
||||
void rlViewport(int x, int y, int width, int height); // Set the viewport area
|
||||
|
@ -340,50 +389,48 @@ void rlColor4f(float x, float y, float z, float w); // Define one vertex (color)
|
|||
// 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(void); // Disable texture usage
|
||||
void rlEnableTexture(unsigned int id); // Enable texture usage
|
||||
void rlDisableTexture(void); // Disable texture usage
|
||||
void rlTextureParameters(unsigned int id, int param, int value); // Set texture parameters (filter, wrap)
|
||||
void rlEnableRenderTexture(unsigned int id); // Enable render texture (fbo)
|
||||
void rlDisableRenderTexture(void); // Disable render texture (fbo), return to default framebuffer
|
||||
void rlEnableDepthTest(void); // Enable depth test
|
||||
void rlDisableDepthTest(void); // Disable depth test
|
||||
void rlEnableWireMode(void); // Enable wire mode
|
||||
void rlDisableWireMode(void); // Disable wire mode
|
||||
void rlDeleteTextures(unsigned int id); // Delete OpenGL texture from GPU
|
||||
void rlEnableRenderTexture(unsigned int id); // Enable render texture (fbo)
|
||||
void rlDisableRenderTexture(void); // Disable render texture (fbo), return to default framebuffer
|
||||
void rlEnableDepthTest(void); // Enable depth test
|
||||
void rlDisableDepthTest(void); // Disable depth test
|
||||
void rlEnableWireMode(void); // Enable wire mode
|
||||
void rlDisableWireMode(void); // Disable wire mode
|
||||
void rlDeleteTextures(unsigned int id); // Delete OpenGL texture from GPU
|
||||
void rlDeleteRenderTextures(RenderTexture2D target); // Delete render textures (fbo) from GPU
|
||||
void rlDeleteShader(unsigned int id); // Delete OpenGL shader program from GPU
|
||||
void rlDeleteVertexArrays(unsigned int id); // Unload vertex data (VAO) from GPU memory
|
||||
void rlDeleteBuffers(unsigned int id); // Unload vertex data (VBO) from GPU memory
|
||||
void rlClearColor(byte r, byte g, byte b, byte a); // Clear color buffer with color
|
||||
void rlClearScreenBuffers(void); // Clear used screen buffers (color and depth)
|
||||
int rlGetVersion(void); // Returns current OpenGL version
|
||||
void rlDeleteShader(unsigned int id); // Delete OpenGL shader program from GPU
|
||||
void rlDeleteVertexArrays(unsigned int id); // Unload vertex data (VAO) from GPU memory
|
||||
void rlDeleteBuffers(unsigned int id); // Unload vertex data (VBO) from GPU memory
|
||||
void rlClearColor(byte r, byte g, byte b, byte a); // Clear color buffer with color
|
||||
void rlClearScreenBuffers(void); // Clear used screen buffers (color and depth)
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Functions Declaration - rlgl functionality
|
||||
//------------------------------------------------------------------------------------
|
||||
void rlglInit(int width, int height); // Initialize rlgl (buffers, shaders, textures, states)
|
||||
void rlglClose(void); // De-init rlgl
|
||||
void rlglDraw(void); // Draw VAO/VBO
|
||||
void rlglLoadExtensions(void *loader); // Load OpenGL extensions
|
||||
void rlglClose(void); // De-inititialize rlgl (buffers, shaders, textures)
|
||||
void rlglDraw(void); // Update and Draw default buffers (lines, triangles, quads)
|
||||
|
||||
unsigned int rlglLoadTexture(void *data, int width, int height, int format, int mipmapCount); // Load texture in GPU
|
||||
RenderTexture2D rlglLoadRenderTexture(int width, int height); // Load a texture to be used for rendering (fbo with color and depth attachments)
|
||||
void rlglUpdateTexture(unsigned int id, int width, int height, int format, const void *data); // Update GPU texture with new data
|
||||
void rlglGenerateMipmaps(Texture2D *texture); // Generate mipmap data for selected texture
|
||||
int rlGetVersion(void); // Returns current OpenGL version
|
||||
void rlLoadExtensions(void *loader); // Load OpenGL extensions
|
||||
Vector3 rlUnproject(Vector3 source, Matrix proj, Matrix view); // Get world coordinates from screen coordinates
|
||||
|
||||
void rlglLoadMesh(Mesh *mesh, bool dynamic); // Upload vertex data into GPU and provided VAO/VBO ids
|
||||
void rlglUpdateMesh(Mesh mesh, int buffer, int numVertex); // Update vertex data on GPU (upload new data to one buffer)
|
||||
void rlglDrawMesh(Mesh mesh, Material material, Matrix transform); // Draw a 3d mesh with material and transform
|
||||
void rlglUnloadMesh(Mesh *mesh); // Unload mesh data from CPU and GPU
|
||||
// Textures data management
|
||||
unsigned int rlLoadTexture(void *data, int width, int height, int format, int mipmapCount); // Load texture in GPU
|
||||
void rlUpdateTexture(unsigned int id, int width, int height, int format, const void *data); // Update GPU texture with new data
|
||||
void rlUnloadTexture(unsigned int id);
|
||||
void rlGenerateMipmaps(Texture2D *texture); // Generate mipmap data for selected texture
|
||||
void *rlReadTexturePixels(Texture2D texture); // Read texture pixel data
|
||||
unsigned char *rlReadScreenPixels(int width, int height); // Read screen pixel data (color buffer)
|
||||
RenderTexture2D rlLoadRenderTexture(int width, int height); // Load a texture to be used for rendering (fbo with color and depth attachments)
|
||||
|
||||
Vector3 rlglUnproject(Vector3 source, Matrix proj, Matrix view); // Get world coordinates from screen coordinates
|
||||
|
||||
unsigned char *rlglReadScreenPixels(int width, int height); // Read screen pixel data (color buffer)
|
||||
void *rlglReadTexturePixels(Texture2D texture); // Read texture pixel data
|
||||
|
||||
// VR functions exposed to core module but not to raylib users
|
||||
void BeginVrDrawing(void); // Begin VR drawing configuration
|
||||
void EndVrDrawing(void); // End VR drawing process (and desktop mirror)
|
||||
// Vertex data management
|
||||
void rlLoadMesh(Mesh *mesh, bool dynamic); // Upload vertex data into GPU and provided VAO/VBO ids
|
||||
void rlUpdateMesh(Mesh mesh, int buffer, int numVertex); // Update vertex data on GPU (upload new data to one buffer)
|
||||
void rlDrawMesh(Mesh mesh, Material material, Matrix transform); // Draw a 3d mesh with material and transform
|
||||
void rlUnloadMesh(Mesh *mesh); // Unload mesh data from CPU and GPU
|
||||
|
||||
// NOTE: There is a set of shader related functions that are available to end user,
|
||||
// to avoid creating function wrappers through core module, they have been directly declared in raylib.h
|
||||
|
@ -393,35 +440,43 @@ void EndVrDrawing(void); // End VR drawing process (and deskt
|
|||
// Shaders System Functions (Module: rlgl)
|
||||
// NOTE: This functions are useless when using OpenGL 1.1
|
||||
//------------------------------------------------------------------------------------
|
||||
Shader LoadShader(char *vsFileName, char *fsFileName); // Load a custom shader and bind default locations
|
||||
void UnloadShader(Shader shader); // Unload a custom shader from memory
|
||||
Shader LoadShader(char *vsFileName, char *fsFileName); // Load a custom shader and bind default locations
|
||||
void UnloadShader(Shader shader); // Unload a custom shader from memory
|
||||
|
||||
Shader GetDefaultShader(void); // Get default shader
|
||||
Shader GetStandardShader(void); // Get default shader
|
||||
Texture2D GetDefaultTexture(void); // Get default texture
|
||||
Shader GetShaderDefault(void); // Get default shader
|
||||
Texture2D GetTextureDefault(void); // Get default texture
|
||||
|
||||
// Shader configuration functions
|
||||
int GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location
|
||||
void SetShaderValue(Shader shader, int uniformLoc, float *value, int size); // Set shader uniform value (float)
|
||||
void SetShaderValuei(Shader shader, int uniformLoc, int *value, int size); // Set shader uniform value (int)
|
||||
void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat); // Set shader uniform value (matrix 4x4)
|
||||
|
||||
void SetMatrixProjection(Matrix proj); // Set a custom projection matrix (replaces internal projection matrix)
|
||||
void SetMatrixModelview(Matrix view); // Set a custom modelview matrix (replaces internal modelview matrix)
|
||||
|
||||
void BeginShaderMode(Shader shader); // Begin custom shader drawing
|
||||
void EndShaderMode(void); // End custom shader drawing (use default shader)
|
||||
void BeginBlendMode(int mode); // Begin blending mode (alpha, additive, multiplied)
|
||||
void EndBlendMode(void); // End blending mode (reset to default: alpha blending)
|
||||
// Texture maps generation (PBR)
|
||||
// NOTE: Required shaders should be provided
|
||||
Texture2D GenTextureCubemap(Shader shader, Texture2D skyHDR, int size); // Generate cubemap texture from HDR texture
|
||||
Texture2D GenTextureIrradiance(Shader shader, Texture2D cubemap, int size); // Generate irradiance texture using cubemap data
|
||||
Texture2D GenTexturePrefilter(Shader shader, Texture2D cubemap, int size); // Generate prefilter texture using cubemap data
|
||||
Texture2D GenTextureBRDF(Shader shader, Texture2D cubemap, int size); // Generate BRDF texture using cubemap data
|
||||
|
||||
void TraceLog(int msgType, const char *text, ...);
|
||||
float *MatrixToFloat(Matrix mat);
|
||||
// Shading and blending
|
||||
void BeginShaderMode(Shader shader); // Begin custom shader drawing
|
||||
void EndShaderMode(void); // End custom shader drawing (use default shader)
|
||||
void BeginBlendMode(int mode); // Begin blending mode (alpha, additive, multiplied)
|
||||
void EndBlendMode(void); // End blending mode (reset to default: alpha blending)
|
||||
|
||||
void InitVrSimulator(int vrDevice); // Init VR simulator for selected device
|
||||
void CloseVrSimulator(void); // Close VR simulator for current device
|
||||
void UpdateVrTracking(Camera *camera); // Update VR tracking (position and orientation) and camera
|
||||
void ToggleVrMode(void); // Enable/Disable VR experience (device or simulator)
|
||||
void BeginVrDrawing(void); // Begin VR stereo rendering
|
||||
void EndVrDrawing(void); // End VR stereo rendering
|
||||
// VR simulator functionality
|
||||
VrDeviceInfo GetVrDeviceInfo(int vrDeviceType); // Get VR device information for some standard devices
|
||||
void InitVrSimulator(VrDeviceInfo info); // Init VR simulator for selected device parameters
|
||||
void CloseVrSimulator(void); // Close VR simulator for current device
|
||||
void UpdateVrTracking(Camera *camera); // Update VR tracking (position and orientation) and camera
|
||||
void ToggleVrMode(void); // Enable/Disable VR experience (device or simulator)
|
||||
void BeginVrDrawing(void); // Begin VR stereo rendering
|
||||
void EndVrDrawing(void); // End VR stereo rendering
|
||||
|
||||
void TraceLog(int msgType, const char *text, ...); // Show trace log messages (LOG_INFO, LOG_WARNING, LOG_ERROR, LOG_DEBUG)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
158
raylib/rres.h
158
raylib/rres.h
|
@ -34,6 +34,14 @@
|
|||
*
|
||||
**********************************************************************************************/
|
||||
|
||||
/*
|
||||
References:
|
||||
RIFF file-format: http://www.johnloomis.org/cpe102/asgn/asgn1/riff.html
|
||||
ZIP file-format: https://en.wikipedia.org/wiki/Zip_(file_format)
|
||||
http://www.onicos.com/staff/iz/formats/zip.html
|
||||
XNB file-format: http://xbox.create.msdn.com/en-US/sample/xnb_format
|
||||
*/
|
||||
|
||||
#ifndef RRES_H
|
||||
#define RRES_H
|
||||
|
||||
|
@ -75,6 +83,9 @@
|
|||
void *data; // Resource data pointer (4 byte)
|
||||
} RRESData;
|
||||
|
||||
// RRES type (pointer to RRESData array)
|
||||
typedef struct RRESData *RRES; // Resource pointer
|
||||
|
||||
// RRESData type
|
||||
typedef enum {
|
||||
RRES_TYPE_RAW = 0,
|
||||
|
@ -83,12 +94,25 @@
|
|||
RRES_TYPE_VERTEX,
|
||||
RRES_TYPE_TEXT,
|
||||
RRES_TYPE_FONT_IMAGE,
|
||||
RRES_TYPE_FONT_CHARDATA, // Character { int value, recX, recY, recWidth, recHeight, offsetX, offsetY, xAdvance }
|
||||
RRES_TYPE_FONT_CHARDATA, // CharInfo { int value, recX, recY, recWidth, recHeight, offsetX, offsetY, xAdvance }
|
||||
RRES_TYPE_DIRECTORY
|
||||
} RRESDataType;
|
||||
|
||||
// RRES type (pointer to RRESData array)
|
||||
typedef struct RRESData *RRES;
|
||||
// Parameters information depending on resource type
|
||||
|
||||
// RRES_TYPE_RAW params: <custom>
|
||||
// RRES_TYPE_IMAGE params: width, height, mipmaps, format
|
||||
// RRES_TYPE_WAVE params: sampleCount, sampleRate, sampleSize, channels
|
||||
// RRES_TYPE_VERTEX params: vertexCount, vertexType, vertexFormat // Use masks instead?
|
||||
// RRES_TYPE_TEXT params: charsCount, cultureCode
|
||||
// RRES_TYPE_FONT_IMAGE params: width, height, format, mipmaps;
|
||||
// RRES_TYPE_FONT_CHARDATA params: charsCount, baseSize
|
||||
// RRES_TYPE_DIRECTORY params: fileCount, directoryCount
|
||||
|
||||
// SpriteFont = RRES_TYPE_FONT_IMAGE chunk + RRES_TYPE_FONT_DATA chunk
|
||||
// Mesh = multiple RRES_TYPE_VERTEX chunks
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
|
@ -103,6 +127,54 @@
|
|||
RRESDEF RRES LoadResource(const char *fileName, int rresId);
|
||||
RRESDEF void UnloadResource(RRES rres);
|
||||
|
||||
/*
|
||||
QUESTION: How to load each type of data from RRES ?
|
||||
|
||||
rres->type == RRES_TYPE_RAW
|
||||
unsigned char data = (unsigned char *)rres[0]->data;
|
||||
|
||||
rres->type == RRES_TYPE_IMAGE
|
||||
Image image;
|
||||
image.data = rres[0]->data; // Be careful, duplicate pointer
|
||||
image.width = rres[0]->param1;
|
||||
image.height = rres[0]->param2;
|
||||
image.mipmaps = rres[0]->param3;
|
||||
image.format = rres[0]->format;
|
||||
|
||||
rres->type == RRES_TYPE_WAVE
|
||||
Wave wave;
|
||||
wave.data = rres[0]->data;
|
||||
wave.sampleCount = rres[0]->param1;
|
||||
wave.sampleRate = rres[0]->param2;
|
||||
wave.sampleSize = rres[0]->param3;
|
||||
wave.channels = rres[0]->param4;
|
||||
|
||||
rres->type == RRES_TYPE_VERTEX (multiple parts)
|
||||
Mesh mesh;
|
||||
mesh.vertexCount = rres[0]->param1;
|
||||
mesh.vertices = (float *)rres[0]->data;
|
||||
mesh.texcoords = (float *)rres[1]->data;
|
||||
mesh.normals = (float *)rres[2]->data;
|
||||
mesh.tangents = (float *)rres[3]->data;
|
||||
mesh.tangents = (unsigned char *)rres[4]->data;
|
||||
|
||||
rres->type == RRES_TYPE_TEXT
|
||||
unsigned char *text = (unsigned char *)rres->data;
|
||||
Shader shader = LoadShaderText(text, rres->param1); Shader LoadShaderText(const char *shdrText, int length);
|
||||
|
||||
rres->type == RRES_TYPE_FONT_IMAGE (multiple parts)
|
||||
rres->type == RRES_TYPE_FONT_CHARDATA
|
||||
SpriteFont font;
|
||||
font.texture = LoadTextureFromImage(image); // rres[0]
|
||||
font.chars = (CharInfo *)rres[1]->data;
|
||||
font.charsCount = rres[1]->param1;
|
||||
font.baseSize = rres[1]->param2;
|
||||
|
||||
rres->type == RRES_TYPE_DIRECTORY
|
||||
unsigned char *fileNames = (unsigned char *)rres[0]->data; // fileNames separed by \n
|
||||
int filesCount = rres[0]->param1;
|
||||
*/
|
||||
|
||||
#endif // RRES_H
|
||||
|
||||
|
||||
|
@ -169,6 +241,7 @@ typedef enum {
|
|||
// gzip, zopfli, lzo, zstd // Other compression algorythms...
|
||||
} RRESCompressionType;
|
||||
|
||||
// Encryption types
|
||||
typedef enum {
|
||||
RRES_CRYPTO_NONE = 0, // No data encryption
|
||||
RRES_CRYPTO_XOR, // XOR (128 bit) encryption
|
||||
|
@ -179,6 +252,7 @@ typedef enum {
|
|||
// twofish, RC5, RC6 // Other encryption algorythm...
|
||||
} RRESEncryptionType;
|
||||
|
||||
// Image/Texture data type
|
||||
typedef enum {
|
||||
RRES_IM_UNCOMP_GRAYSCALE = 1, // 8 bit per pixel (no alpha)
|
||||
RRES_IM_UNCOMP_GRAY_ALPHA, // 16 bpp (2 channels)
|
||||
|
@ -201,6 +275,7 @@ typedef enum {
|
|||
//...
|
||||
} RRESImageFormat;
|
||||
|
||||
// Vertex data type
|
||||
typedef enum {
|
||||
RRES_VERT_POSITION,
|
||||
RRES_VERT_TEXCOORD1,
|
||||
|
@ -214,6 +289,7 @@ typedef enum {
|
|||
//...
|
||||
} RRESVertexType;
|
||||
|
||||
// Vertex data format type
|
||||
typedef enum {
|
||||
RRES_VERT_BYTE,
|
||||
RRES_VERT_SHORT,
|
||||
|
@ -252,7 +328,7 @@ RRESDEF RRES LoadResource(const char *fileName, int rresId)
|
|||
|
||||
FILE *rresFile = fopen(fileName, "rb");
|
||||
|
||||
if (rresFile == NULL) TraceLog(WARNING, "[%s] rRES raylib resource file could not be opened", fileName);
|
||||
if (rresFile == NULL) TraceLog(LOG_WARNING, "[%s] rRES raylib resource file could not be opened", fileName);
|
||||
else
|
||||
{
|
||||
// Read rres file info header
|
||||
|
@ -266,7 +342,7 @@ RRESDEF RRES LoadResource(const char *fileName, int rresId)
|
|||
// Verify "rRES" identifier
|
||||
if ((fileHeader.id[0] != 'r') && (fileHeader.id[1] != 'R') && (fileHeader.id[2] != 'E') && (fileHeader.id[3] != 'S'))
|
||||
{
|
||||
TraceLog(WARNING, "[%s] This is not a valid raylib resource file", fileName);
|
||||
TraceLog(LOG_WARNING, "[%s] This is not a valid raylib resource file", fileName);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -275,10 +351,10 @@ RRESDEF RRES LoadResource(const char *fileName, int rresId)
|
|||
// Read resource info and parameters
|
||||
fread(&infoHeader, sizeof(RRESInfoHeader), 1, rresFile);
|
||||
|
||||
rres = (RRES)malloc(sizeof(RRESData)*infoHeader.partsCount);
|
||||
|
||||
if (infoHeader.id == rresId)
|
||||
{
|
||||
rres = (RRES)malloc(sizeof(RRESData)*infoHeader.partsCount);
|
||||
|
||||
// Load all required resources parts
|
||||
for (int k = 0; k < infoHeader.partsCount; k++)
|
||||
{
|
||||
|
@ -305,7 +381,7 @@ RRESDEF RRES LoadResource(const char *fileName, int rresId)
|
|||
}
|
||||
else rres[k].data = data;
|
||||
|
||||
if (rres[k].data != NULL) TraceLog(INFO, "[%s][ID %i] Resource data loaded successfully", fileName, (int)infoHeader.id);
|
||||
if (rres[k].data != NULL) TraceLog(LOG_INFO, "[%s][ID %i] Resource data loaded successfully", fileName, (int)infoHeader.id);
|
||||
|
||||
// Read next part
|
||||
fread(&infoHeader, sizeof(RRESInfoHeader), 1, rresFile);
|
||||
|
@ -318,7 +394,7 @@ RRESDEF RRES LoadResource(const char *fileName, int rresId)
|
|||
}
|
||||
}
|
||||
|
||||
if (rres[0].data == NULL) TraceLog(WARNING, "[%s][ID %i] Requested resource could not be found", fileName, (int)rresId);
|
||||
if (rres[0].data == NULL) TraceLog(LOG_WARNING, "[%s][ID %i] Requested resource could not be found", fileName, (int)rresId);
|
||||
}
|
||||
|
||||
fclose(rresFile);
|
||||
|
@ -327,8 +403,11 @@ RRESDEF RRES LoadResource(const char *fileName, int rresId)
|
|||
return rres;
|
||||
}
|
||||
|
||||
// Unload resource data
|
||||
RRESDEF void UnloadResource(RRES rres)
|
||||
{
|
||||
// TODO: When you load resource... how many parts conform it? depends on type? --> Not clear...
|
||||
|
||||
if (rres[0].data != NULL) free(rres[0].data);
|
||||
}
|
||||
|
||||
|
@ -349,7 +428,7 @@ static void *DecompressData(const unsigned char *data, unsigned long compSize, i
|
|||
// Check correct memory allocation
|
||||
if (uncompData == NULL)
|
||||
{
|
||||
TraceLog(WARNING, "Out of memory while decompressing data");
|
||||
TraceLog(LOG_WARNING, "Out of memory while decompressing data");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -358,18 +437,18 @@ static void *DecompressData(const unsigned char *data, unsigned long compSize, i
|
|||
|
||||
if (tempUncompSize == -1)
|
||||
{
|
||||
TraceLog(WARNING, "Data decompression failed");
|
||||
TraceLog(LOG_WARNING, "Data decompression failed");
|
||||
RRES_FREE(uncompData);
|
||||
}
|
||||
|
||||
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);
|
||||
TraceLog(LOG_WARNING, "Expected uncompressed size do not match, data may be corrupted");
|
||||
TraceLog(LOG_WARNING, " -- Expected uncompressed size: %i", uncompSize);
|
||||
TraceLog(LOG_WARNING, " -- Returned uncompressed size: %i", tempUncompSize);
|
||||
}
|
||||
|
||||
TraceLog(INFO, "Data decompressed successfully from %u bytes to %u bytes", (mz_uint32)compSize, (mz_uint32)tempUncompSize);
|
||||
TraceLog(LOG_INFO, "Data decompressed successfully from %u bytes to %u bytes", (mz_uint32)compSize, (mz_uint32)tempUncompSize);
|
||||
}
|
||||
|
||||
return uncompData;
|
||||
|
@ -377,61 +456,28 @@ static void *DecompressData(const unsigned char *data, unsigned long compSize, i
|
|||
|
||||
// Some required functions for rres standalone module version
|
||||
#if defined(RRES_STANDALONE)
|
||||
// Outputs a trace log message (INFO, ERROR, WARNING)
|
||||
// NOTE: If a file has been init, output log is written there
|
||||
// Show trace log messages (LOG_INFO, LOG_WARNING, LOG_ERROR, LOG_DEBUG)
|
||||
void TraceLog(int logType, const char *text, ...)
|
||||
{
|
||||
va_list args;
|
||||
int traceDebugMsgs = 0;
|
||||
|
||||
#ifdef DO_NOT_TRACE_DEBUG_MSGS
|
||||
traceDebugMsgs = 0;
|
||||
#endif
|
||||
va_start(args, text);
|
||||
|
||||
switch (msgType)
|
||||
{
|
||||
case LOG_INFO: fprintf(stdout, "INFO: "); break;
|
||||
case LOG_ERROR: fprintf(stdout, "ERROR: "); break;
|
||||
case LOG_WARNING: fprintf(stdout, "WARNING: "); break;
|
||||
case LOG_DEBUG: if (traceDebugMsgs) fprintf(stdout, "DEBUG: "); break;
|
||||
case LOG_DEBUG: fprintf(stdout, "DEBUG: "); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
if ((msgType != LOG_DEBUG) || ((msgType == LOG_DEBUG) && (traceDebugMsgs)))
|
||||
{
|
||||
va_start(args, text);
|
||||
vfprintf(stdout, text, args);
|
||||
va_end(args);
|
||||
vfprintf(stdout, text, args);
|
||||
fprintf(stdout, "\n");
|
||||
|
||||
fprintf(stdout, "\n");
|
||||
}
|
||||
va_end(args);
|
||||
|
||||
if (msgType == ERROR) exit(1); // If ERROR message, exit program
|
||||
if (msgType == LOG_ERROR) exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // RAYGUI_IMPLEMENTATION
|
||||
|
||||
/*
|
||||
Mesh LoadMeshEx(int numVertex, float *vData, float *vtData, float *vnData, Color *cData);
|
||||
Mesh LoadMeshEx(rres.param1, rres.data, rres.data + offset, rres.data + offset*2, rres.data + offset*3);
|
||||
|
||||
Shader LoadShader(const char *vsText, int vsLength);
|
||||
Shader LoadShaderV(rres.data, rres.param1);
|
||||
|
||||
// Parameters information depending on resource type
|
||||
|
||||
// RRES_TYPE_IMAGE params: imgWidth, imgHeight, format, mipmaps;
|
||||
// RRES_TYPE_WAVE params: sampleCount, sampleRate, sampleSize, channels;
|
||||
// RRES_TYPE_FONT_IMAGE params: imgWidth, imgHeight, format, mipmaps;
|
||||
// RRES_TYPE_FONT_DATA params: charsCount, baseSize
|
||||
// RRES_TYPE_VERTEX params: vertexCount, vertexType, vertexFormat // Use masks instead?
|
||||
// RRES_TYPE_TEXT params: charsCount, cultureCode
|
||||
// RRES_TYPE_DIRECTORY params: fileCount, directoryCount
|
||||
|
||||
// SpriteFont = RRES_TYPE_FONT_IMAGE chunk + RRES_TYPE_FONT_DATA chunk
|
||||
// Mesh = multiple RRES_TYPE_VERTEX chunks
|
||||
|
||||
Ref: RIFF file-format: http://www.johnloomis.org/cpe102/asgn/asgn1/riff.html
|
||||
|
||||
*/
|
||||
#endif // RRES_IMPLEMENTATION
|
||||
|
|
|
@ -20,12 +20,12 @@ static const char vDistortionShaderStr[] =
|
|||
"out vec2 fragTexCoord; \n"
|
||||
"out vec4 fragColor; \n"
|
||||
#endif
|
||||
"uniform mat4 mvpMatrix; \n"
|
||||
"uniform mat4 mvp; \n"
|
||||
"void main() \n"
|
||||
"{ \n"
|
||||
" fragTexCoord = vertexTexCoord; \n"
|
||||
" fragColor = vertexColor; \n"
|
||||
" gl_Position = mvpMatrix*vec4(vertexPosition, 1.0); \n"
|
||||
" gl_Position = mvp*vec4(vertexPosition, 1.0); \n"
|
||||
"} \n";
|
||||
|
||||
// Fragment shader definition to embed, no external file required
|
||||
|
|
|
@ -13,17 +13,55 @@ type VrDevice int32
|
|||
|
||||
// Head Mounted Display devices
|
||||
const (
|
||||
HmdDefaultDevice VrDevice = C.HMD_DEFAULT_DEVICE
|
||||
HmdOculusRiftDk2 VrDevice = C.HMD_OCULUS_RIFT_DK2
|
||||
HmdOculusRiftCv1 VrDevice = C.HMD_OCULUS_RIFT_CV1
|
||||
HmdValveHtcVive VrDevice = C.HMD_VALVE_HTC_VIVE
|
||||
HmdSamsungGearVr VrDevice = C.HMD_SAMSUNG_GEAR_VR
|
||||
HmdGoogleCardboard VrDevice = C.HMD_GOOGLE_CARDBOARD
|
||||
HmdSonyPlaystationVr VrDevice = C.HMD_SONY_PLAYSTATION_VR
|
||||
HmdRazerOsvr VrDevice = C.HMD_RAZER_OSVR
|
||||
HmdFoveVr VrDevice = C.HMD_FOVE_VR
|
||||
HmdDefaultDevice VrDevice = iota
|
||||
HmdOculusRiftDk2
|
||||
HmdOculusRiftCv1
|
||||
HmdOculusGo
|
||||
HmdValveHtcVive
|
||||
HmdSonyPsvr
|
||||
)
|
||||
|
||||
// VrDeviceInfo - Head-Mounted-Display device parameters
|
||||
type VrDeviceInfo struct {
|
||||
// HMD horizontal resolution in pixels
|
||||
hResolution int
|
||||
// HMD vertical resolution in pixels
|
||||
vResolution int
|
||||
// HMD horizontal size in meters
|
||||
hScreenSize float32
|
||||
// HMD vertical size in meters
|
||||
vScreenSize float32
|
||||
// HMD screen center in meters
|
||||
vScreenCenter float32
|
||||
// HMD distance between eye and display in meters
|
||||
eyeToScreenDistance float32
|
||||
// HMD lens separation distance in meters
|
||||
lensSeparationDistance float32
|
||||
// HMD IPD (distance between pupils) in meters
|
||||
interpupillaryDistance float32
|
||||
// HMD lens distortion constant parameters
|
||||
lensDistortionValues [4]float32
|
||||
// HMD chromatic aberration correction parameters
|
||||
chromaAbCorrection [4]float32
|
||||
}
|
||||
|
||||
func (v *VrDeviceInfo) cptr() *C.VrDeviceInfo {
|
||||
return (*C.VrDeviceInfo)(unsafe.Pointer(v))
|
||||
}
|
||||
|
||||
// NewVrDeviceInfo - Returns new VrDeviceInfo
|
||||
func NewVrDeviceInfo(hResolution, vResolution int, hScreenSize, vScreenSize, vScreenCenter, eyeToScreenDistance,
|
||||
lensSeparationDistance, interpupillaryDistance float32, lensDistortionValues, chromaAbCorrection [4]float32) VrDeviceInfo {
|
||||
|
||||
return VrDeviceInfo{hResolution, vResolution, hScreenSize, vScreenSize, vScreenCenter, eyeToScreenDistance,
|
||||
lensSeparationDistance, interpupillaryDistance, lensDistortionValues, chromaAbCorrection}
|
||||
}
|
||||
|
||||
// NewVrDeviceInfoFromPointer - Returns new VrDeviceInfo from pointer
|
||||
func NewVrDeviceInfoFromPointer(ptr unsafe.Pointer) VrDeviceInfo {
|
||||
return *(*VrDeviceInfo)(ptr)
|
||||
}
|
||||
|
||||
// BlendMode type
|
||||
type BlendMode int32
|
||||
|
||||
|
@ -38,32 +76,8 @@ const (
|
|||
type Shader struct {
|
||||
// Shader program id
|
||||
ID uint32
|
||||
// Vertex attribute location point (default-location = 0)
|
||||
VertexLoc int32
|
||||
// Texcoord attribute location point (default-location = 1)
|
||||
TexcoordLoc int32
|
||||
// Texcoord2 attribute location point (default-location = 5)
|
||||
Texcoord2Loc int32
|
||||
// Normal attribute location point (default-location = 2)
|
||||
NormalLoc int32
|
||||
// Tangent attribute location point (default-location = 4)
|
||||
TangentLoc int32
|
||||
// Color attibute location point (default-location = 3)
|
||||
ColorLoc int32
|
||||
// ModelView-Projection matrix uniform location point (vertex shader)
|
||||
MvpLoc int32
|
||||
// Diffuse color uniform location point (fragment shader)
|
||||
ColDiffuseLoc int32
|
||||
// Ambient color uniform location point (fragment shader)
|
||||
ColAmbientLoc int32
|
||||
// Specular color uniform location point (fragment shader)
|
||||
ColSpecularLoc int32
|
||||
// Map texture uniform location point (default-texture-unit = 0)
|
||||
MapTexture0Loc int32
|
||||
// Map texture uniform location point (default-texture-unit = 1)
|
||||
MapTexture1Loc int32
|
||||
// Map texture uniform location point (default-texture-unit = 2)
|
||||
MapTexture2Loc int32
|
||||
// Shader locations array
|
||||
Locs [MaxShaderLocations]int32
|
||||
}
|
||||
|
||||
func (s *Shader) cptr() *C.Shader {
|
||||
|
@ -71,8 +85,8 @@ func (s *Shader) cptr() *C.Shader {
|
|||
}
|
||||
|
||||
// NewShader - Returns new Shader
|
||||
func NewShader(id uint32, vertexLoc, texcoordLoc, texcoord2Loc, normalLoc, tangentLoc, colorLoc, mvpLoc, colDiffuseLoc, colAmbientLoc, colSpecularLoc, mapTexture0Loc, mapTexture1Loc, mapTexture2Loc int32) Shader {
|
||||
return Shader{id, vertexLoc, texcoordLoc, texcoord2Loc, normalLoc, tangentLoc, colorLoc, mvpLoc, colDiffuseLoc, colAmbientLoc, colSpecularLoc, mapTexture0Loc, mapTexture1Loc, mapTexture2Loc}
|
||||
func NewShader(id uint32, locs [MaxShaderLocations]int32) Shader {
|
||||
return Shader{id, locs}
|
||||
}
|
||||
|
||||
// NewShaderFromPointer - Returns new Shader from pointer
|
||||
|
@ -98,16 +112,16 @@ func UnloadShader(shader Shader) {
|
|||
C.UnloadShader(*cshader)
|
||||
}
|
||||
|
||||
// GetDefaultShader - Get default shader
|
||||
func GetDefaultShader() Shader {
|
||||
ret := C.GetDefaultShader()
|
||||
// GetShaderDefault - Get default shader
|
||||
func GetShaderDefault() Shader {
|
||||
ret := C.GetShaderDefault()
|
||||
v := NewShaderFromPointer(unsafe.Pointer(&ret))
|
||||
return v
|
||||
}
|
||||
|
||||
// GetDefaultTexture - Get default texture
|
||||
func GetDefaultTexture() *Texture2D {
|
||||
ret := C.GetDefaultTexture()
|
||||
// GetTextureDefault - Get default texture
|
||||
func GetTextureDefault() *Texture2D {
|
||||
ret := C.GetTextureDefault()
|
||||
v := NewTexture2DFromPointer(unsafe.Pointer(&ret))
|
||||
return &v
|
||||
}
|
||||
|
@ -117,6 +131,7 @@ func GetShaderLocation(shader Shader, uniformName string) int32 {
|
|||
cshader := shader.cptr()
|
||||
cuniformName := C.CString(uniformName)
|
||||
defer C.free(unsafe.Pointer(cuniformName))
|
||||
|
||||
ret := C.GetShaderLocation(*cshader, cuniformName)
|
||||
v := (int32)(ret)
|
||||
return v
|
||||
|
@ -160,6 +175,50 @@ func SetMatrixModelview(view Matrix) {
|
|||
C.SetMatrixModelview(*cview)
|
||||
}
|
||||
|
||||
// GenTextureCubemap - Generate cubemap texture from HDR texture
|
||||
func GenTextureCubemap(shader Shader, skyHDR Texture2D, size int) Texture2D {
|
||||
cshader := shader.cptr()
|
||||
cskyHDR := skyHDR.cptr()
|
||||
csize := (C.int)(size)
|
||||
|
||||
ret := C.GenTextureCubemap(*cshader, *cskyHDR, csize)
|
||||
v := NewTexture2DFromPointer(unsafe.Pointer(&ret))
|
||||
return v
|
||||
}
|
||||
|
||||
// GenTextureIrradiance - Generate irradiance texture using cubemap data
|
||||
func GenTextureIrradiance(shader Shader, cubemap Texture2D, size int) Texture2D {
|
||||
cshader := shader.cptr()
|
||||
ccubemap := cubemap.cptr()
|
||||
csize := (C.int)(size)
|
||||
|
||||
ret := C.GenTextureIrradiance(*cshader, *ccubemap, csize)
|
||||
v := NewTexture2DFromPointer(unsafe.Pointer(&ret))
|
||||
return v
|
||||
}
|
||||
|
||||
// GenTexturePrefilter - Generate prefilter texture using cubemap data
|
||||
func GenTexturePrefilter(shader Shader, cubemap Texture2D, size int) Texture2D {
|
||||
cshader := shader.cptr()
|
||||
ccubemap := cubemap.cptr()
|
||||
csize := (C.int)(size)
|
||||
|
||||
ret := C.GenTexturePrefilter(*cshader, *ccubemap, csize)
|
||||
v := NewTexture2DFromPointer(unsafe.Pointer(&ret))
|
||||
return v
|
||||
}
|
||||
|
||||
// GenTextureBRDF - Generate BRDF texture using cubemap data
|
||||
func GenTextureBRDF(shader Shader, cubemap Texture2D, size int) Texture2D {
|
||||
cshader := shader.cptr()
|
||||
ccubemap := cubemap.cptr()
|
||||
csize := (C.int)(size)
|
||||
|
||||
ret := C.GenTextureBRDF(*cshader, *ccubemap, csize)
|
||||
v := NewTexture2DFromPointer(unsafe.Pointer(&ret))
|
||||
return v
|
||||
}
|
||||
|
||||
// BeginShaderMode - Begin custom shader drawing
|
||||
func BeginShaderMode(shader Shader) {
|
||||
cshader := shader.cptr()
|
||||
|
@ -182,10 +241,18 @@ func EndBlendMode() {
|
|||
C.EndBlendMode()
|
||||
}
|
||||
|
||||
// GetVrDeviceInfo - Get VR device information for some standard devices
|
||||
func GetVrDeviceInfo(vrDevice VrDevice) VrDeviceInfo {
|
||||
cvrDevice := (C.int)(vrDevice)
|
||||
ret := C.GetVrDeviceInfo(cvrDevice)
|
||||
v := NewVrDeviceInfoFromPointer(unsafe.Pointer(&ret))
|
||||
return v
|
||||
}
|
||||
|
||||
// InitVrSimulator - Init VR simulator for selected device
|
||||
func InitVrSimulator(vdDevice VrDevice) {
|
||||
cvdDevice := (C.int)(vdDevice)
|
||||
C.InitVrSimulator(cvdDevice)
|
||||
func InitVrSimulator(vrDeviceInfo VrDeviceInfo) {
|
||||
cvrDeviceInfo := vrDeviceInfo.cptr()
|
||||
C.InitVrSimulator(*cvrDeviceInfo)
|
||||
}
|
||||
|
||||
// CloseVrSimulator - Close VR simulator for current device
|
||||
|
|
|
@ -119,11 +119,11 @@ void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color)
|
|||
float d = sqrtf(dx*dx + dy*dy);
|
||||
float angle = asinf(dy/d);
|
||||
|
||||
rlEnableTexture(GetDefaultTexture().id);
|
||||
rlEnableTexture(GetTextureDefault().id);
|
||||
|
||||
rlPushMatrix();
|
||||
rlTranslatef((float)startPos.x, (float)startPos.y, 0);
|
||||
rlRotatef(-RAD2DEG*angle, 0, 0, 1);
|
||||
rlRotatef(RAD2DEG*angle, 0, 0, 1);
|
||||
rlTranslatef(0, -thick/2.0f, 0);
|
||||
|
||||
rlBegin(RL_QUADS);
|
||||
|
@ -203,7 +203,7 @@ void DrawCircleV(Vector2 center, float radius, Color color)
|
|||
}
|
||||
else if ((rlGetVersion() == OPENGL_21) || (rlGetVersion() == OPENGL_33) || (rlGetVersion() == OPENGL_ES_20))
|
||||
{
|
||||
rlEnableTexture(GetDefaultTexture().id); // Default white texture
|
||||
rlEnableTexture(GetTextureDefault().id); // Default white texture
|
||||
|
||||
rlBegin(RL_QUADS);
|
||||
for (int i = 0; i < 360; i += 20)
|
||||
|
@ -253,7 +253,7 @@ void DrawRectangleRec(Rectangle rec, Color color)
|
|||
|
||||
void DrawRectanglePro(Rectangle rec, Vector2 origin, float rotation, Color color)
|
||||
{
|
||||
rlEnableTexture(GetDefaultTexture().id);
|
||||
rlEnableTexture(GetTextureDefault().id);
|
||||
|
||||
rlPushMatrix();
|
||||
rlTranslatef((float)rec.x, (float)rec.y, 0);
|
||||
|
@ -274,19 +274,66 @@ void DrawRectanglePro(Rectangle rec, Vector2 origin, float rotation, Color color
|
|||
rlDisableTexture();
|
||||
}
|
||||
|
||||
// Draw a gradient-filled rectangle
|
||||
// Draw a vertical-gradient-filled rectangle
|
||||
// NOTE: Gradient goes from bottom (color1) to top (color2)
|
||||
void DrawRectangleGradient(int posX, int posY, int width, int height, Color color1, Color color2)
|
||||
void DrawRectangleGradientV(int posX, int posY, int width, int height, Color color1, Color color2)
|
||||
{
|
||||
rlBegin(RL_TRIANGLES);
|
||||
rlColor4ub(color1.r, color1.g, color1.b, color1.a); rlVertex2i(posX, posY);
|
||||
rlColor4ub(color2.r, color2.g, color2.b, color2.a); rlVertex2i(posX, posY + height);
|
||||
rlColor4ub(color2.r, color2.g, color2.b, color2.a); rlVertex2i(posX + width, posY + height);
|
||||
DrawRectangleGradientEx((Rectangle){ posX, posY, width, height }, color1, color2, color2, color1);
|
||||
}
|
||||
|
||||
rlColor4ub(color1.r, color1.g, color1.b, color1.a); rlVertex2i(posX, posY);
|
||||
rlColor4ub(color2.r, color2.g, color2.b, color2.a); rlVertex2i(posX + width, posY + height);
|
||||
rlColor4ub(color1.r, color1.g, color1.b, color1.a); rlVertex2i(posX + width, posY);
|
||||
// Draw a horizontal-gradient-filled rectangle
|
||||
// NOTE: Gradient goes from bottom (color1) to top (color2)
|
||||
void DrawRectangleGradientH(int posX, int posY, int width, int height, Color color1, Color color2)
|
||||
{
|
||||
DrawRectangleGradientEx((Rectangle){ posX, posY, width, height }, color1, color1, color2, color2);
|
||||
}
|
||||
|
||||
// Draw a gradient-filled rectangle
|
||||
// NOTE: Colors refer to corners, starting at top-lef corner and counter-clockwise
|
||||
void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3, Color col4)
|
||||
{
|
||||
rlEnableTexture(GetTextureDefault().id); // Default white texture
|
||||
|
||||
rlBegin(RL_QUADS);
|
||||
rlNormal3f(0.0f, 0.0f, 1.0f);
|
||||
|
||||
rlColor4ub(col1.r, col1.g, col1.b, col1.a);
|
||||
rlTexCoord2f(0.0f, 0.0f);
|
||||
rlVertex2f(rec.x, rec.y);
|
||||
|
||||
rlColor4ub(col2.r, col2.g, col2.b, col2.a);
|
||||
rlTexCoord2f(0.0f, 1.0f);
|
||||
rlVertex2f(rec.x, rec.y + rec.height);
|
||||
|
||||
rlColor4ub(col3.r, col3.g, col3.b, col3.a);
|
||||
rlTexCoord2f(1.0f, 1.0f);
|
||||
rlVertex2f(rec.x + rec.width, rec.y + rec.height);
|
||||
|
||||
rlColor4ub(col4.r, col4.g, col4.b, col4.a);
|
||||
rlTexCoord2f(1.0f, 0.0f);
|
||||
rlVertex2f(rec.x + rec.width, rec.y);
|
||||
rlEnd();
|
||||
|
||||
// Draw rectangle using font texture white character
|
||||
/*
|
||||
rlTexCoord2f((float)GetDefaultFont().chars[95].rec.x/GetDefaultFont().texture.width,
|
||||
(float)GetDefaultFont().chars[95].rec.y/GetDefaultFont().texture.height);
|
||||
rlVertex2f(rec.x, rec.y);
|
||||
|
||||
rlTexCoord2f((float)GetDefaultFont().chars[95].rec.x/GetDefaultFont().texture.width,
|
||||
(float)(GetDefaultFont().chars[95].rec.y + GetDefaultFont().chars[95].rec.height)/GetDefaultFont().texture.height);
|
||||
rlVertex2f(rec.x, rec.y + rec.height);
|
||||
|
||||
rlTexCoord2f((float)(GetDefaultFont().chars[95].rec.x + GetDefaultFont().chars[95].rec.width)/GetDefaultFont().texture.width,
|
||||
(float)(GetDefaultFont().chars[95].rec.y + GetDefaultFont().chars[95].rec.height)/GetDefaultFont().texture.height);
|
||||
rlVertex2f(rec.x + rec.width, rec.y + rec.height);
|
||||
|
||||
rlTexCoord2f((float)(GetDefaultFont().chars[95].rec.x + GetDefaultFont().chars[95].rec.width)/GetDefaultFont().texture.width,
|
||||
(float)GetDefaultFont().chars[95].rec.y/GetDefaultFont().texture.height);
|
||||
rlVertex2f(rec.x + rec.width, rec.y);
|
||||
*/
|
||||
|
||||
rlDisableTexture();
|
||||
}
|
||||
|
||||
// Draw a color-filled rectangle (Vector version)
|
||||
|
@ -309,7 +356,7 @@ void DrawRectangleV(Vector2 position, Vector2 size, Color color)
|
|||
}
|
||||
else if ((rlGetVersion() == OPENGL_21) || (rlGetVersion() == OPENGL_33) || (rlGetVersion() == OPENGL_ES_20))
|
||||
{
|
||||
rlEnableTexture(GetDefaultTexture().id); // Default white texture
|
||||
rlEnableTexture(GetTextureDefault().id); // Default white texture
|
||||
|
||||
rlBegin(RL_QUADS);
|
||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
|
@ -362,6 +409,14 @@ void DrawRectangleLines(int posX, int posY, int width, int height, Color color)
|
|||
}
|
||||
}
|
||||
|
||||
// Draw rectangle using text character (char: 127)
|
||||
// NOTE: Useful to avoid changing to default white texture
|
||||
void DrawRectangleT(int posX, int posY, int width, int height, Color color)
|
||||
{
|
||||
DrawTexturePro(GetDefaultFont().texture, GetDefaultFont().chars[95].rec,
|
||||
(Rectangle){ posX, posY, width, height }, (Vector2){ 0, 0 }, 0.0f, color);
|
||||
}
|
||||
|
||||
// Draw a triangle
|
||||
void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color)
|
||||
{
|
||||
|
@ -376,7 +431,7 @@ void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color)
|
|||
}
|
||||
else if ((rlGetVersion() == OPENGL_21) || (rlGetVersion() == OPENGL_33) || (rlGetVersion() == OPENGL_ES_20))
|
||||
{
|
||||
rlEnableTexture(GetDefaultTexture().id); // Default white texture
|
||||
rlEnableTexture(GetTextureDefault().id); // Default white texture
|
||||
|
||||
rlBegin(RL_QUADS);
|
||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
|
@ -627,6 +682,8 @@ Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2)
|
|||
// NOTE: Required for DrawLineBezier()
|
||||
static float EaseCubicInOut(float t, float b, float c, float d)
|
||||
{
|
||||
if ((t/=d/2) < 1) return (c/2*t*t*t + b);
|
||||
return (c/2*((t-=2)*t*t + 2) + b);
|
||||
}
|
||||
if ((t /= 0.5*d) < 1)
|
||||
return 0.5*c*t*t*t + b;
|
||||
t -= 2;
|
||||
return 0.5*c*(t*t*t + 2) + b;
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ import "C"
|
|||
import "unsafe"
|
||||
|
||||
// DrawPixel - Draw a pixel
|
||||
func DrawPixel(posX int32, posY int32, color Color) {
|
||||
func DrawPixel(posX, posY int32, color Color) {
|
||||
cposX := (C.int)(posX)
|
||||
cposY := (C.int)(posY)
|
||||
ccolor := color.cptr()
|
||||
|
@ -23,7 +23,7 @@ func DrawPixelV(position Vector2, color Color) {
|
|||
}
|
||||
|
||||
// DrawLine - Draw a line
|
||||
func DrawLine(startPosX int32, startPosY int32, endPosX int32, endPosY int32, color Color) {
|
||||
func DrawLine(startPosX, startPosY, endPosX, endPosY int32, color Color) {
|
||||
cstartPosX := (C.int)(startPosX)
|
||||
cstartPosY := (C.int)(startPosY)
|
||||
cendPosX := (C.int)(endPosX)
|
||||
|
@ -33,7 +33,7 @@ func DrawLine(startPosX int32, startPosY int32, endPosX int32, endPosY int32, co
|
|||
}
|
||||
|
||||
// DrawLineV - Draw a line (Vector version)
|
||||
func DrawLineV(startPos Vector2, endPos Vector2, color Color) {
|
||||
func DrawLineV(startPos, endPos Vector2, color Color) {
|
||||
cstartPos := startPos.cptr()
|
||||
cendPos := endPos.cptr()
|
||||
ccolor := color.cptr()
|
||||
|
@ -41,7 +41,7 @@ func DrawLineV(startPos Vector2, endPos Vector2, color Color) {
|
|||
}
|
||||
|
||||
// DrawLineEx - Draw a line defining thickness
|
||||
func DrawLineEx(startPos Vector2, endPos Vector2, thick float32, color Color) {
|
||||
func DrawLineEx(startPos, endPos Vector2, thick float32, color Color) {
|
||||
cstartPos := startPos.cptr()
|
||||
cendPos := endPos.cptr()
|
||||
cthick := (C.float)(thick)
|
||||
|
@ -50,7 +50,7 @@ func DrawLineEx(startPos Vector2, endPos Vector2, thick float32, color Color) {
|
|||
}
|
||||
|
||||
// DrawLineBezier - Draw a line using cubic-bezier curves in-out
|
||||
func DrawLineBezier(startPos Vector2, endPos Vector2, thick float32, color Color) {
|
||||
func DrawLineBezier(startPos, endPos Vector2, thick float32, color Color) {
|
||||
cstartPos := startPos.cptr()
|
||||
cendPos := endPos.cptr()
|
||||
cthick := (C.float)(thick)
|
||||
|
@ -59,7 +59,7 @@ func DrawLineBezier(startPos Vector2, endPos Vector2, thick float32, color Color
|
|||
}
|
||||
|
||||
// DrawCircle - Draw a color-filled circle
|
||||
func DrawCircle(centerX int32, centerY int32, radius float32, color Color) {
|
||||
func DrawCircle(centerX, centerY int32, radius float32, color Color) {
|
||||
ccenterX := (C.int)(centerX)
|
||||
ccenterY := (C.int)(centerY)
|
||||
cradius := (C.float)(radius)
|
||||
|
@ -68,7 +68,7 @@ func DrawCircle(centerX int32, centerY int32, radius float32, color Color) {
|
|||
}
|
||||
|
||||
// DrawCircleGradient - Draw a gradient-filled circle
|
||||
func DrawCircleGradient(centerX int32, centerY int32, radius float32, color1 Color, color2 Color) {
|
||||
func DrawCircleGradient(centerX, centerY int32, radius float32, color1, color2 Color) {
|
||||
ccenterX := (C.int)(centerX)
|
||||
ccenterY := (C.int)(centerY)
|
||||
cradius := (C.float)(radius)
|
||||
|
@ -86,7 +86,7 @@ func DrawCircleV(center Vector2, radius float32, color Color) {
|
|||
}
|
||||
|
||||
// DrawCircleLines - Draw circle outline
|
||||
func DrawCircleLines(centerX int32, centerY int32, radius float32, color Color) {
|
||||
func DrawCircleLines(centerX, centerY int32, radius float32, color Color) {
|
||||
ccenterX := (C.int)(centerX)
|
||||
ccenterY := (C.int)(centerY)
|
||||
cradius := (C.float)(radius)
|
||||
|
@ -95,7 +95,7 @@ func DrawCircleLines(centerX int32, centerY int32, radius float32, color Color)
|
|||
}
|
||||
|
||||
// DrawRectangle - Draw a color-filled rectangle
|
||||
func DrawRectangle(posX int32, posY int32, width int32, height int32, color Color) {
|
||||
func DrawRectangle(posX, posY, width, height int32, color Color) {
|
||||
cposX := (C.int)(posX)
|
||||
cposY := (C.int)(posY)
|
||||
cwidth := (C.int)(width)
|
||||
|
@ -120,15 +120,36 @@ func DrawRectanglePro(rec Rectangle, origin Vector2, rotation float32, color Col
|
|||
C.DrawRectanglePro(*crec, *corigin, crotation, *ccolor)
|
||||
}
|
||||
|
||||
// DrawRectangleGradient - Draw a gradient-filled rectangle
|
||||
func DrawRectangleGradient(posX int32, posY int32, width int32, height int32, color1 Color, color2 Color) {
|
||||
// DrawRectangleGradientV - Draw a vertical-gradient-filled rectangle
|
||||
func DrawRectangleGradientV(posX, posY, width, height int32, color1, color2 Color) {
|
||||
cposX := (C.int)(posX)
|
||||
cposY := (C.int)(posY)
|
||||
cwidth := (C.int)(width)
|
||||
cheight := (C.int)(height)
|
||||
ccolor1 := color1.cptr()
|
||||
ccolor2 := color2.cptr()
|
||||
C.DrawRectangleGradient(cposX, cposY, cwidth, cheight, *ccolor1, *ccolor2)
|
||||
C.DrawRectangleGradientV(cposX, cposY, cwidth, cheight, *ccolor1, *ccolor2)
|
||||
}
|
||||
|
||||
// DrawRectangleGradientH - Draw a horizontal-gradient-filled rectangle
|
||||
func DrawRectangleGradientH(posX, posY, width, height int32, color1, color2 Color) {
|
||||
cposX := (C.int)(posX)
|
||||
cposY := (C.int)(posY)
|
||||
cwidth := (C.int)(width)
|
||||
cheight := (C.int)(height)
|
||||
ccolor1 := color1.cptr()
|
||||
ccolor2 := color2.cptr()
|
||||
C.DrawRectangleGradientH(cposX, cposY, cwidth, cheight, *ccolor1, *ccolor2)
|
||||
}
|
||||
|
||||
// DrawRectangleGradientEx - Draw a gradient-filled rectangle with custom vertex colors
|
||||
func DrawRectangleGradientEx(rec Rectangle, color1, color2, color3, color4 Color) {
|
||||
crec := rec.cptr()
|
||||
ccolor1 := color1.cptr()
|
||||
ccolor2 := color2.cptr()
|
||||
ccolor3 := color3.cptr()
|
||||
ccolor4 := color4.cptr()
|
||||
C.DrawRectangleGradientEx(*crec, *ccolor1, *ccolor2, *ccolor3, *ccolor4)
|
||||
}
|
||||
|
||||
// DrawRectangleV - Draw a color-filled rectangle (Vector version)
|
||||
|
@ -140,7 +161,7 @@ func DrawRectangleV(position Vector2, size Vector2, color Color) {
|
|||
}
|
||||
|
||||
// DrawRectangleLines - Draw rectangle outline
|
||||
func DrawRectangleLines(posX int32, posY int32, width int32, height int32, color Color) {
|
||||
func DrawRectangleLines(posX, posY, width, height int32, color Color) {
|
||||
cposX := (C.int)(posX)
|
||||
cposY := (C.int)(posY)
|
||||
cwidth := (C.int)(width)
|
||||
|
@ -149,8 +170,18 @@ func DrawRectangleLines(posX int32, posY int32, width int32, height int32, color
|
|||
C.DrawRectangleLines(cposX, cposY, cwidth, cheight, *ccolor)
|
||||
}
|
||||
|
||||
// DrawRectangleT - Draw rectangle using text character
|
||||
func DrawRectangleT(posX, posY, width, height int32, color Color) {
|
||||
cposX := (C.int)(posX)
|
||||
cposY := (C.int)(posY)
|
||||
cwidth := (C.int)(width)
|
||||
cheight := (C.int)(height)
|
||||
ccolor := color.cptr()
|
||||
C.DrawRectangleT(cposX, cposY, cwidth, cheight, *ccolor)
|
||||
}
|
||||
|
||||
// DrawTriangle - Draw a color-filled triangle
|
||||
func DrawTriangle(v1 Vector2, v2 Vector2, v3 Vector2, color Color) {
|
||||
func DrawTriangle(v1, v2, v3 Vector2, color Color) {
|
||||
cv1 := v1.cptr()
|
||||
cv2 := v2.cptr()
|
||||
cv3 := v3.cptr()
|
||||
|
@ -159,7 +190,7 @@ func DrawTriangle(v1 Vector2, v2 Vector2, v3 Vector2, color Color) {
|
|||
}
|
||||
|
||||
// DrawTriangleLines - Draw triangle outline
|
||||
func DrawTriangleLines(v1 Vector2, v2 Vector2, v3 Vector2, color Color) {
|
||||
func DrawTriangleLines(v1, v2, v3 Vector2, color Color) {
|
||||
cv1 := v1.cptr()
|
||||
cv2 := v2.cptr()
|
||||
cv3 := v3.cptr()
|
||||
|
@ -168,7 +199,7 @@ func DrawTriangleLines(v1 Vector2, v2 Vector2, v3 Vector2, color Color) {
|
|||
}
|
||||
|
||||
// DrawPoly - Draw a regular polygon (Vector version)
|
||||
func DrawPoly(center Vector2, sides int32, radius float32, rotation float32, color Color) {
|
||||
func DrawPoly(center Vector2, sides int32, radius, rotation float32, color Color) {
|
||||
ccenter := center.cptr()
|
||||
csides := (C.int)(sides)
|
||||
cradius := (C.float)(radius)
|
||||
|
@ -194,7 +225,7 @@ func DrawPolyExLines(points []Vector2, numPoints int32, color Color) {
|
|||
}
|
||||
|
||||
// CheckCollisionRecs - Check collision between two rectangles
|
||||
func CheckCollisionRecs(rec1 Rectangle, rec2 Rectangle) bool {
|
||||
func CheckCollisionRecs(rec1, rec2 Rectangle) bool {
|
||||
crec1 := rec1.cptr()
|
||||
crec2 := rec2.cptr()
|
||||
ret := C.CheckCollisionRecs(*crec1, *crec2)
|
||||
|
@ -224,7 +255,7 @@ func CheckCollisionCircleRec(center Vector2, radius float32, rec Rectangle) bool
|
|||
}
|
||||
|
||||
// GetCollisionRec - Get collision rectangle for two rectangles collision
|
||||
func GetCollisionRec(rec1 Rectangle, rec2 Rectangle) Rectangle {
|
||||
func GetCollisionRec(rec1, rec2 Rectangle) Rectangle {
|
||||
crec1 := rec1.cptr()
|
||||
crec2 := rec2.cptr()
|
||||
ret := C.GetCollisionRec(*crec1, *crec2)
|
||||
|
@ -252,7 +283,7 @@ func CheckCollisionPointCircle(point Vector2, center Vector2, radius float32) bo
|
|||
}
|
||||
|
||||
// CheckCollisionPointTriangle - Check if point is inside a triangle
|
||||
func CheckCollisionPointTriangle(point Vector2, p1 Vector2, p2 Vector2, p3 Vector2) bool {
|
||||
func CheckCollisionPointTriangle(point, p1, p2, p3 Vector2) bool {
|
||||
cpoint := point.cptr()
|
||||
cp1 := p1.cptr()
|
||||
cp2 := p2.cptr()
|
||||
|
|
|
@ -139,10 +139,10 @@ extern void LoadDefaultFont(void)
|
|||
0x04000404, 0x4100203c, 0x00000000, 0x00000800, 0xf7df7df0, 0x514bef85, 0xbefbefbe, 0x04513bef, 0x14414500, 0x494a2885, 0xa28a28aa, 0x04510820,
|
||||
0xf44145f0, 0x474a289d, 0xa28a28aa, 0x04510be0, 0x14414510, 0x494a2884, 0xa28a28aa, 0x02910a00, 0xf7df7df0, 0xd14a2f85, 0xbefbe8aa, 0x011f7be0,
|
||||
0x00000000, 0x00400804, 0x20080000, 0x00000000, 0x00000000, 0x00600f84, 0x20080000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0xac000000, 0x00000f01, 0x00000000, 0x00000000, 0x24000000, 0x00000901, 0x00000000, 0x06000000, 0x24000000, 0x00000901, 0x00000000, 0x09108000,
|
||||
0x24fa28a2, 0x00000901, 0x00000000, 0x013e0000, 0x2242252a, 0x00000952, 0x00000000, 0x038a8000, 0x2422222a, 0x00000929, 0x00000000, 0x010a8000,
|
||||
0x2412252a, 0x00000901, 0x00000000, 0x010a8000, 0x24fbe8be, 0x00000901, 0x00000000, 0x0ebe8000, 0xac020000, 0x00000f01, 0x00000000, 0x00048000,
|
||||
0x0003e000, 0x00000000, 0x00000000, 0x00008000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000038, 0x8443b80e, 0x00203a03,
|
||||
0xac000000, 0x00000f01, 0x00000000, 0x00000000, 0x24000000, 0x00000f01, 0x00000000, 0x06000000, 0x24000000, 0x00000f01, 0x00000000, 0x09108000,
|
||||
0x24fa28a2, 0x00000f01, 0x00000000, 0x013e0000, 0x2242252a, 0x00000f52, 0x00000000, 0x038a8000, 0x2422222a, 0x00000f29, 0x00000000, 0x010a8000,
|
||||
0x2412252a, 0x00000f01, 0x00000000, 0x010a8000, 0x24fbe8be, 0x00000f01, 0x00000000, 0x0ebe8000, 0xac020000, 0x00000f01, 0x00000000, 0x00048000,
|
||||
0x0003e000, 0x00000f00, 0x00000000, 0x00008000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000038, 0x8443b80e, 0x00203a03,
|
||||
0x02bea080, 0xf0000020, 0xc452208a, 0x04202b02, 0xf8029122, 0x07f0003b, 0xe44b388e, 0x02203a02, 0x081e8a1c, 0x0411e92a, 0xf4420be0, 0x01248202,
|
||||
0xe8140414, 0x05d104ba, 0xe7c3b880, 0x00893a0a, 0x283c0e1c, 0x04500902, 0xc4400080, 0x00448002, 0xe8208422, 0x04500002, 0x80400000, 0x05200002,
|
||||
0x083e8e00, 0x04100002, 0x804003e0, 0x07000042, 0xf8008400, 0x07f00003, 0x80400000, 0x04000022, 0x00000000, 0x00000000, 0x80400000, 0x04000002,
|
||||
|
@ -255,8 +255,8 @@ extern void LoadDefaultFont(void)
|
|||
}
|
||||
|
||||
defaultFont.baseSize = defaultFont.chars[0].rec.height;
|
||||
|
||||
TraceLog(INFO, "[TEX ID %i] Default font loaded successfully", defaultFont.texture.id);
|
||||
|
||||
TraceLog(LOG_INFO, "[TEX ID %i] Default font loaded successfully", defaultFont.texture.id);
|
||||
}
|
||||
|
||||
// Unload raylib default font
|
||||
|
@ -330,7 +330,7 @@ SpriteFont LoadSpriteFont(const char *fileName)
|
|||
|
||||
if (spriteFont.texture.id == 0)
|
||||
{
|
||||
TraceLog(WARNING, "[%s] SpriteFont could not be loaded, using default font", fileName);
|
||||
TraceLog(LOG_WARNING, "[%s] SpriteFont could not be loaded, using default font", fileName);
|
||||
spriteFont = GetDefaultFont();
|
||||
}
|
||||
else SetTextureFilter(spriteFont.texture, FILTER_POINT); // By default we set point filter (best performance)
|
||||
|
@ -364,7 +364,7 @@ SpriteFont LoadSpriteFontEx(const char *fileName, int fontSize, int charsCount,
|
|||
|
||||
if (spriteFont.texture.id == 0)
|
||||
{
|
||||
TraceLog(WARNING, "[%s] SpriteFont could not be generated, using default font", fileName);
|
||||
TraceLog(LOG_WARNING, "[%s] SpriteFont could not be generated, using default font", fileName);
|
||||
spriteFont = GetDefaultFont();
|
||||
}
|
||||
|
||||
|
@ -380,7 +380,7 @@ void UnloadSpriteFont(SpriteFont spriteFont)
|
|||
UnloadTexture(spriteFont.texture);
|
||||
free(spriteFont.chars);
|
||||
|
||||
TraceLog(DEBUG, "Unloaded sprite font data");
|
||||
TraceLog(LOG_DEBUG, "Unloaded sprite font data");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -443,7 +443,7 @@ void DrawTextEx(SpriteFont spriteFont, const char *text, Vector2 position, float
|
|||
index = GetCharIndex(spriteFont, (int)letter + 64);
|
||||
i++;
|
||||
}
|
||||
else index = GetCharIndex(spriteFont, (int)text[i]);
|
||||
else index = GetCharIndex(spriteFont, (unsigned char)text[i]);
|
||||
|
||||
DrawTexturePro(spriteFont.texture, spriteFont.chars[index].rec,
|
||||
(Rectangle){ position.x + textOffsetX + spriteFont.chars[index].offsetX*scaleFactor,
|
||||
|
@ -632,6 +632,7 @@ static SpriteFont LoadImageFont(Image image, Color key, int firstChar)
|
|||
{
|
||||
if (!COLOR_EQUAL(pixels[y*image.width + x], key)) break;
|
||||
}
|
||||
|
||||
if (!COLOR_EQUAL(pixels[y*image.width + x], key)) break;
|
||||
}
|
||||
|
||||
|
@ -677,7 +678,7 @@ static SpriteFont LoadImageFont(Image image, Color key, int firstChar)
|
|||
xPosToRead = charSpacing;
|
||||
}
|
||||
|
||||
TraceLog(DEBUG, "SpriteFont data parsed correctly from image");
|
||||
TraceLog(LOG_DEBUG, "SpriteFont data parsed correctly from image");
|
||||
|
||||
// NOTE: We need to remove key color borders from image to avoid weird
|
||||
// artifacts on texture scaling when using FILTER_BILINEAR or FILTER_TRILINEAR
|
||||
|
@ -713,7 +714,7 @@ static SpriteFont LoadImageFont(Image image, Color key, int firstChar)
|
|||
|
||||
spriteFont.baseSize = spriteFont.chars[0].rec.height;
|
||||
|
||||
TraceLog(INFO, "Image file loaded correctly as SpriteFont");
|
||||
TraceLog(LOG_INFO, "Image file loaded correctly as SpriteFont");
|
||||
|
||||
return spriteFont;
|
||||
}
|
||||
|
@ -743,7 +744,7 @@ static SpriteFont LoadBMFont(const char *fileName)
|
|||
|
||||
if (fntFile == NULL)
|
||||
{
|
||||
TraceLog(WARNING, "[%s] FNT file could not be opened", fileName);
|
||||
TraceLog(LOG_WARNING, "[%s] FNT file could not be opened", fileName);
|
||||
return font;
|
||||
}
|
||||
|
||||
|
@ -756,20 +757,20 @@ static SpriteFont LoadBMFont(const char *fileName)
|
|||
searchPoint = strstr(buffer, "lineHeight");
|
||||
sscanf(searchPoint, "lineHeight=%i base=%i scaleW=%i scaleH=%i", &fontSize, &base, &texWidth, &texHeight);
|
||||
|
||||
TraceLog(DEBUG, "[%s] Font size: %i", fileName, fontSize);
|
||||
TraceLog(DEBUG, "[%s] Font texture scale: %ix%i", fileName, texWidth, texHeight);
|
||||
TraceLog(LOG_DEBUG, "[%s] Font size: %i", fileName, fontSize);
|
||||
TraceLog(LOG_DEBUG, "[%s] Font texture scale: %ix%i", fileName, texWidth, texHeight);
|
||||
|
||||
fgets(buffer, MAX_BUFFER_SIZE, fntFile);
|
||||
searchPoint = strstr(buffer, "file");
|
||||
sscanf(searchPoint, "file=\"%128[^\"]\"", texFileName);
|
||||
|
||||
TraceLog(DEBUG, "[%s] Font texture filename: %s", fileName, texFileName);
|
||||
TraceLog(LOG_DEBUG, "[%s] Font texture filename: %s", fileName, texFileName);
|
||||
|
||||
fgets(buffer, MAX_BUFFER_SIZE, fntFile);
|
||||
searchPoint = strstr(buffer, "count");
|
||||
sscanf(searchPoint, "count=%i", &charsCount);
|
||||
|
||||
TraceLog(DEBUG, "[%s] Font num chars: %i", fileName, charsCount);
|
||||
TraceLog(LOG_DEBUG, "[%s] Font num chars: %i", fileName, charsCount);
|
||||
|
||||
// Compose correct path using route of .fnt file (fileName) and texFileName
|
||||
char *texPath = NULL;
|
||||
|
@ -785,7 +786,7 @@ static SpriteFont LoadBMFont(const char *fileName)
|
|||
strncat(texPath, fileName, strlen(fileName) - strlen(lastSlash) + 1);
|
||||
strncat(texPath, texFileName, strlen(texFileName));
|
||||
|
||||
TraceLog(DEBUG, "[%s] Font texture loading path: %s", fileName, texPath);
|
||||
TraceLog(LOG_DEBUG, "[%s] Font texture loading path: %s", fileName, texPath);
|
||||
|
||||
Image imFont = LoadImage(texPath);
|
||||
|
||||
|
@ -832,7 +833,7 @@ static SpriteFont LoadBMFont(const char *fileName)
|
|||
UnloadSpriteFont(font);
|
||||
font = GetDefaultFont();
|
||||
}
|
||||
else TraceLog(INFO, "[%s] SpriteFont loaded successfully", fileName);
|
||||
else TraceLog(LOG_INFO, "[%s] SpriteFont loaded successfully", fileName);
|
||||
|
||||
return font;
|
||||
}
|
||||
|
@ -853,7 +854,7 @@ static SpriteFont LoadTTF(const char *fileName, int fontSize, int charsCount, in
|
|||
float guessSize = ceilf((float)fontSize*3/4)*ceilf(sqrtf((float)charsCount));
|
||||
int textureSize = (int)powf(2, ceilf(logf((float)guessSize)/logf(2))); // Calculate next POT
|
||||
|
||||
TraceLog(INFO, "TTF spritefont loading: Predicted texture size: %ix%i", textureSize, textureSize);
|
||||
TraceLog(LOG_INFO, "TTF spritefont loading: Predicted texture size: %ix%i", textureSize, textureSize);
|
||||
|
||||
unsigned char *ttfBuffer = (unsigned char *)malloc(MAX_TTF_SIZE*1024*1024);
|
||||
unsigned char *dataBitmap = (unsigned char *)malloc(textureSize*textureSize*sizeof(unsigned char)); // One channel bitmap returned!
|
||||
|
@ -865,22 +866,34 @@ static SpriteFont LoadTTF(const char *fileName, int fontSize, int charsCount, in
|
|||
|
||||
if (ttfFile == NULL)
|
||||
{
|
||||
TraceLog(WARNING, "[%s] TTF file could not be opened", fileName);
|
||||
TraceLog(LOG_WARNING, "[%s] TTF file could not be opened", fileName);
|
||||
return font;
|
||||
}
|
||||
|
||||
// NOTE: We try reading up to 16 MB of elements of 1 byte
|
||||
fread(ttfBuffer, 1, MAX_TTF_SIZE*1024*1024, ttfFile);
|
||||
|
||||
// Find font baseline (vertical origin of the font)
|
||||
// NOTE: This value is required because y-offset depends on it!
|
||||
stbtt_fontinfo fontInfo;
|
||||
int ascent, baseline;
|
||||
float scale;
|
||||
|
||||
if (fontChars[0] != 32) TraceLog(WARNING, "TTF spritefont loading: first character is not SPACE(32) character");
|
||||
stbtt_InitFont(&fontInfo, ttfBuffer, 0);
|
||||
scale = stbtt_ScaleForPixelHeight(&fontInfo, fontSize);
|
||||
stbtt_GetFontVMetrics(&fontInfo, &ascent, 0, 0);
|
||||
baseline = (int)(ascent*scale);
|
||||
|
||||
|
||||
if (fontChars[0] != 32) TraceLog(LOG_WARNING, "TTF spritefont loading: first character is not SPACE(32) character");
|
||||
|
||||
// NOTE: Using stb_truetype crappy packing method, no guarante the font fits the image...
|
||||
// TODO: Replace this function by a proper packing method and support random chars order,
|
||||
// we already receive a list (fontChars) with the ordered expected characters
|
||||
int result = stbtt_BakeFontBitmap(ttfBuffer, 0, fontSize, dataBitmap, textureSize, textureSize, fontChars[0], charsCount, charData);
|
||||
|
||||
//if (result > 0) TraceLog(INFO, "TTF spritefont loading: first unused row of generated bitmap: %i", result);
|
||||
if (result < 0) TraceLog(WARNING, "TTF spritefont loading: Not all the characters fit in the font");
|
||||
|
||||
//if (result > 0) TraceLog(LOG_INFO, "TTF spritefont loading: first unused row of generated bitmap: %i", result);
|
||||
if (result < 0) TraceLog(LOG_WARNING, "TTF spritefont loading: Not all the characters fit in the font");
|
||||
|
||||
free(ttfBuffer);
|
||||
|
||||
|
@ -923,7 +936,7 @@ static SpriteFont LoadTTF(const char *fileName, int fontSize, int charsCount, in
|
|||
font.chars[i].rec.height = (int)charData[i].y1 - (int)charData[i].y0;
|
||||
|
||||
font.chars[i].offsetX = charData[i].xoff;
|
||||
font.chars[i].offsetY = charData[i].yoff;
|
||||
font.chars[i].offsetY = baseline + charData[i].yoff;
|
||||
font.chars[i].advanceX = (int)charData[i].xadvance;
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -174,7 +174,7 @@ func LoadImage(fileName string) *Image {
|
|||
}
|
||||
|
||||
// LoadImageEx - Load image data from Color array data (RGBA - 32bit)
|
||||
func LoadImageEx(pixels []Color, width int32, height int32) *Image {
|
||||
func LoadImageEx(pixels []Color, width, height int32) *Image {
|
||||
cpixels := pixels[0].cptr()
|
||||
cwidth := (C.int)(width)
|
||||
cheight := (C.int)(height)
|
||||
|
@ -184,7 +184,7 @@ func LoadImageEx(pixels []Color, width int32, height int32) *Image {
|
|||
}
|
||||
|
||||
// LoadImagePro - Load image from raw data with parameters
|
||||
func LoadImagePro(data []byte, width int32, height int32, format TextureFormat) *Image {
|
||||
func LoadImagePro(data []byte, width, height int32, format TextureFormat) *Image {
|
||||
cdata := unsafe.Pointer(&data[0])
|
||||
cwidth := (C.int)(width)
|
||||
cheight := (C.int)(height)
|
||||
|
@ -195,7 +195,7 @@ func LoadImagePro(data []byte, width int32, height int32, format TextureFormat)
|
|||
}
|
||||
|
||||
// LoadImageRaw - Load image data from RAW file
|
||||
func LoadImageRaw(fileName string, width int32, height int32, format TextureFormat, headerSize int32) *Image {
|
||||
func LoadImageRaw(fileName string, width, height int32, format TextureFormat, headerSize int32) *Image {
|
||||
cfileName := C.CString(fileName)
|
||||
defer C.free(unsafe.Pointer(cfileName))
|
||||
cwidth := (C.int)(width)
|
||||
|
@ -225,7 +225,7 @@ func LoadTextureFromImage(image *Image) Texture2D {
|
|||
}
|
||||
|
||||
// LoadRenderTexture - Load a texture to be used for rendering
|
||||
func LoadRenderTexture(width int32, height int32) RenderTexture2D {
|
||||
func LoadRenderTexture(width, height int32) RenderTexture2D {
|
||||
cwidth := (C.int)(width)
|
||||
cheight := (C.int)(height)
|
||||
ret := C.LoadRenderTexture(cwidth, cheight)
|
||||
|
@ -273,6 +273,15 @@ func UpdateTexture(texture Texture2D, pixels unsafe.Pointer) {
|
|||
C.UpdateTexture(*ctexture, cpixels)
|
||||
}
|
||||
|
||||
// SaveImageAs - Save image to a PNG file
|
||||
func SaveImageAs(name string, image Image) {
|
||||
cname := C.CString(name)
|
||||
defer C.free(unsafe.Pointer(cname))
|
||||
cimage := image.cptr()
|
||||
|
||||
C.SaveImageAs(cname, *cimage)
|
||||
}
|
||||
|
||||
// ImageToPOT - Convert image to POT (power-of-two)
|
||||
func ImageToPOT(image *Image, fillColor Color) {
|
||||
cimage := image.cptr()
|
||||
|
@ -288,14 +297,14 @@ func ImageFormat(image *Image, newFormat int32) {
|
|||
}
|
||||
|
||||
// ImageAlphaMask - Apply alpha mask to image
|
||||
func ImageAlphaMask(image *Image, alphaMask *Image) {
|
||||
func ImageAlphaMask(image, alphaMask *Image) {
|
||||
cimage := image.cptr()
|
||||
calphaMask := alphaMask.cptr()
|
||||
C.ImageAlphaMask(cimage, *calphaMask)
|
||||
}
|
||||
|
||||
// ImageDither - Dither image data to 16bpp or lower (Floyd-Steinberg dithering)
|
||||
func ImageDither(image *Image, rBpp int32, gBpp int32, bBpp int32, aBpp int32) {
|
||||
func ImageDither(image *Image, rBpp, gBpp, bBpp, aBpp int32) {
|
||||
cimage := image.cptr()
|
||||
crBpp := (C.int)(rBpp)
|
||||
cgBpp := (C.int)(gBpp)
|
||||
|
@ -320,7 +329,7 @@ func ImageCrop(image *Image, crop Rectangle) {
|
|||
}
|
||||
|
||||
// ImageResize - Resize an image (bilinear filtering)
|
||||
func ImageResize(image *Image, newWidth int32, newHeight int32) {
|
||||
func ImageResize(image *Image, newWidth, newHeight int32) {
|
||||
cimage := image.cptr()
|
||||
cnewWidth := (C.int)(newWidth)
|
||||
cnewHeight := (C.int)(newHeight)
|
||||
|
@ -328,7 +337,7 @@ func ImageResize(image *Image, newWidth int32, newHeight int32) {
|
|||
}
|
||||
|
||||
// ImageResizeNN - Resize an image (Nearest-Neighbor scaling algorithm)
|
||||
func ImageResizeNN(image *Image, newWidth int32, newHeight int32) {
|
||||
func ImageResizeNN(image *Image, newWidth, newHeight int32) {
|
||||
cimage := image.cptr()
|
||||
cnewWidth := (C.int)(newWidth)
|
||||
cnewHeight := (C.int)(newHeight)
|
||||
|
@ -360,7 +369,7 @@ func ImageTextEx(font SpriteFont, text string, fontSize float32, spacing int32,
|
|||
}
|
||||
|
||||
// ImageDraw - Draw a source image within a destination image
|
||||
func ImageDraw(dst *Image, src *Image, srcRec Rectangle, dstRec Rectangle) {
|
||||
func ImageDraw(dst, src *Image, srcRec, dstRec Rectangle) {
|
||||
cdst := dst.cptr()
|
||||
csrc := src.cptr()
|
||||
csrcRec := srcRec.cptr()
|
||||
|
@ -437,6 +446,101 @@ func ImageColorBrightness(image *Image, brightness int32) {
|
|||
C.ImageColorBrightness(cimage, cbrightness)
|
||||
}
|
||||
|
||||
// GenImageColor - Generate image: plain color
|
||||
func GenImageColor(width, height int, color Color) *Image {
|
||||
cwidth := (C.int)(width)
|
||||
cheight := (C.int)(height)
|
||||
ccolor := color.cptr()
|
||||
|
||||
ret := C.GenImageColor(cwidth, cheight, *ccolor)
|
||||
v := NewImageFromPointer(unsafe.Pointer(&ret))
|
||||
return v
|
||||
}
|
||||
|
||||
// GenImageGradientV - Generate image: vertical gradient
|
||||
func GenImageGradientV(width, height int, top, bottom Color) *Image {
|
||||
cwidth := (C.int)(width)
|
||||
cheight := (C.int)(height)
|
||||
ctop := top.cptr()
|
||||
cbottom := bottom.cptr()
|
||||
|
||||
ret := C.GenImageGradientV(cwidth, cheight, *ctop, *cbottom)
|
||||
v := NewImageFromPointer(unsafe.Pointer(&ret))
|
||||
return v
|
||||
}
|
||||
|
||||
// GenImageGradientH - Generate image: horizontal gradient
|
||||
func GenImageGradientH(width, height int, left, right Color) *Image {
|
||||
cwidth := (C.int)(width)
|
||||
cheight := (C.int)(height)
|
||||
cleft := left.cptr()
|
||||
cright := right.cptr()
|
||||
|
||||
ret := C.GenImageGradientH(cwidth, cheight, *cleft, *cright)
|
||||
v := NewImageFromPointer(unsafe.Pointer(&ret))
|
||||
return v
|
||||
}
|
||||
|
||||
// GenImageGradientRadial - Generate image: radial gradient
|
||||
func GenImageGradientRadial(width, height int, density float32, inner, outer Color) *Image {
|
||||
cwidth := (C.int)(width)
|
||||
cheight := (C.int)(height)
|
||||
cdensity := (C.float)(density)
|
||||
cinner := inner.cptr()
|
||||
couter := outer.cptr()
|
||||
|
||||
ret := C.GenImageGradientRadial(cwidth, cheight, cdensity, *cinner, *couter)
|
||||
v := NewImageFromPointer(unsafe.Pointer(&ret))
|
||||
return v
|
||||
}
|
||||
|
||||
// GenImageChecked - Generate image: checked
|
||||
func GenImageChecked(width, height, checksX, checksY int, col1, col2 Color) *Image {
|
||||
cwidth := (C.int)(width)
|
||||
cheight := (C.int)(height)
|
||||
cchecksX := (C.int)(checksX)
|
||||
cchecksY := (C.int)(checksY)
|
||||
ccol1 := col1.cptr()
|
||||
ccol2 := col2.cptr()
|
||||
|
||||
ret := C.GenImageChecked(cwidth, cheight, cchecksX, cchecksY, *ccol1, *ccol2)
|
||||
v := NewImageFromPointer(unsafe.Pointer(&ret))
|
||||
return v
|
||||
}
|
||||
|
||||
// GenImageWhiteNoise - Generate image: white noise
|
||||
func GenImageWhiteNoise(width, height int, factor float32) *Image {
|
||||
cwidth := (C.int)(width)
|
||||
cheight := (C.int)(height)
|
||||
cfactor := (C.float)(factor)
|
||||
|
||||
ret := C.GenImageWhiteNoise(cwidth, cheight, cfactor)
|
||||
v := NewImageFromPointer(unsafe.Pointer(&ret))
|
||||
return v
|
||||
}
|
||||
|
||||
// GenImagePerlinNoise - Generate image: perlin noise
|
||||
func GenImagePerlinNoise(width, height int, scale float32) *Image {
|
||||
cwidth := (C.int)(width)
|
||||
cheight := (C.int)(height)
|
||||
cscale := (C.float)(scale)
|
||||
|
||||
ret := C.GenImagePerlinNoise(cwidth, cheight, cscale)
|
||||
v := NewImageFromPointer(unsafe.Pointer(&ret))
|
||||
return v
|
||||
}
|
||||
|
||||
// GenImageCellular - Generate image: cellular algorithm. Bigger tileSize means bigger cells
|
||||
func GenImageCellular(width, height, tileSize int) *Image {
|
||||
cwidth := (C.int)(width)
|
||||
cheight := (C.int)(height)
|
||||
ctileSize := (C.int)(tileSize)
|
||||
|
||||
ret := C.GenImageCellular(cwidth, cheight, ctileSize)
|
||||
v := NewImageFromPointer(unsafe.Pointer(&ret))
|
||||
return v
|
||||
}
|
||||
|
||||
// GenTextureMipmaps - Generate GPU mipmaps for a texture
|
||||
func GenTextureMipmaps(texture *Texture2D) {
|
||||
ctexture := texture.cptr()
|
||||
|
@ -475,7 +579,7 @@ func DrawTextureV(texture Texture2D, position Vector2, tint Color) {
|
|||
}
|
||||
|
||||
// DrawTextureEx - Draw a Texture2D with extended parameters
|
||||
func DrawTextureEx(texture Texture2D, position Vector2, rotation float32, scale float32, tint Color) {
|
||||
func DrawTextureEx(texture Texture2D, position Vector2, rotation, scale float32, tint Color) {
|
||||
ctexture := texture.cptr()
|
||||
cposition := position.cptr()
|
||||
crotation := (C.float)(rotation)
|
||||
|
@ -494,7 +598,7 @@ func DrawTextureRec(texture Texture2D, sourceRec Rectangle, position Vector2, ti
|
|||
}
|
||||
|
||||
// DrawTexturePro - Draw a part of a texture defined by a rectangle with 'pro' parameters
|
||||
func DrawTexturePro(texture Texture2D, sourceRec Rectangle, destRec Rectangle, origin Vector2, rotation float32, tint Color) {
|
||||
func DrawTexturePro(texture Texture2D, sourceRec, destRec Rectangle, origin Vector2, rotation float32, tint Color) {
|
||||
ctexture := texture.cptr()
|
||||
csourceRec := sourceRec.cptr()
|
||||
cdestRec := destRec.cptr()
|
||||
|
|
|
@ -14,10 +14,10 @@
|
|||
*
|
||||
* #define SUPPORT_TRACELOG
|
||||
* Show TraceLog() output messages
|
||||
* NOTE: By default DEBUG traces not shown
|
||||
* NOTE: By default LOG_DEBUG traces not shown
|
||||
*
|
||||
* #define SUPPORT_TRACELOG_DEBUG
|
||||
* Show TraceLog() DEBUG messages
|
||||
* Show TraceLog() LOG_DEBUG messages
|
||||
*
|
||||
* DEPENDENCIES:
|
||||
* stb_image_write - BMP/PNG writting functions
|
||||
|
@ -45,8 +45,9 @@
|
|||
**********************************************************************************************/
|
||||
|
||||
#define SUPPORT_TRACELOG // Output tracelog messages
|
||||
//#define SUPPORT_TRACELOG_DEBUG // Avoid DEBUG messages tracing
|
||||
//#define SUPPORT_TRACELOG_DEBUG // Avoid LOG_DEBUG messages tracing
|
||||
|
||||
#include "raylib.h" // WARNING: Required for: LogType enum
|
||||
#include "utils.h"
|
||||
|
||||
#if defined(PLATFORM_ANDROID)
|
||||
|
@ -89,7 +90,7 @@ static int android_close(void *cookie);
|
|||
// Module Functions Definition - Utilities
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Output trace log messages
|
||||
// Show trace log messages (LOG_INFO, LOG_WARNING, LOG_ERROR, LOG_DEBUG)
|
||||
void TraceLog(int msgType, const char *text, ...)
|
||||
{
|
||||
#if defined(SUPPORT_TRACELOG)
|
||||
|
@ -102,10 +103,10 @@ void TraceLog(int msgType, const char *text, ...)
|
|||
|
||||
switch(msgType)
|
||||
{
|
||||
case INFO: strcpy(buffer, "INFO: "); break;
|
||||
case ERROR: strcpy(buffer, "ERROR: "); break;
|
||||
case WARNING: strcpy(buffer, "WARNING: "); break;
|
||||
case DEBUG: strcpy(buffer, "DEBUG: "); break;
|
||||
case LOG_INFO: strcpy(buffer, "INFO: "); break;
|
||||
case LOG_ERROR: strcpy(buffer, "ERROR: "); break;
|
||||
case LOG_WARNING: strcpy(buffer, "WARNING: "); break;
|
||||
case LOG_DEBUG: strcpy(buffer, "DEBUG: "); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
|
@ -118,19 +119,19 @@ void TraceLog(int msgType, const char *text, ...)
|
|||
#if defined(PLATFORM_ANDROID)
|
||||
switch(msgType)
|
||||
{
|
||||
case INFO: __android_log_vprint(ANDROID_LOG_INFO, "raylib", buffer, args); break;
|
||||
case ERROR: __android_log_vprint(ANDROID_LOG_ERROR, "raylib", buffer, args); break;
|
||||
case WARNING: __android_log_vprint(ANDROID_LOG_WARN, "raylib", buffer, args); break;
|
||||
case DEBUG: if (traceDebugMsgs) __android_log_vprint(ANDROID_LOG_DEBUG, "raylib", buffer, args); break;
|
||||
case LOG_INFO: __android_log_vprint(ANDROID_LOG_INFO, "raylib", buffer, args); break;
|
||||
case LOG_ERROR: __android_log_vprint(ANDROID_LOG_ERROR, "raylib", buffer, args); break;
|
||||
case LOG_WARNING: __android_log_vprint(ANDROID_LOG_WARN, "raylib", buffer, args); break;
|
||||
case LOG_DEBUG: if (traceDebugMsgs) __android_log_vprint(ANDROID_LOG_DEBUG, "raylib", buffer, args); break;
|
||||
default: break;
|
||||
}
|
||||
#else
|
||||
if ((msgType != DEBUG) || ((msgType == DEBUG) && (traceDebugMsgs))) vprintf(buffer, args);
|
||||
if ((msgType != LOG_DEBUG) || ((msgType == LOG_DEBUG) && (traceDebugMsgs))) vprintf(buffer, args);
|
||||
#endif
|
||||
|
||||
va_end(args);
|
||||
|
||||
if (msgType == ERROR) exit(1); // If ERROR message, exit program
|
||||
if (msgType == LOG_ERROR) exit(1); // If LOG_ERROR message, exit program
|
||||
|
||||
#endif // SUPPORT_TRACELOG
|
||||
}
|
||||
|
@ -195,7 +196,7 @@ static int android_read(void *cookie, char *buf, int size)
|
|||
|
||||
static int android_write(void *cookie, const char *buf, int size)
|
||||
{
|
||||
TraceLog(ERROR, "Can't provide write access to the APK");
|
||||
TraceLog(LOG_ERROR, "Can't provide write access to the APK");
|
||||
|
||||
return EACCES;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue