mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-07-11 01:25:07 +02:00
Reindent (->tabs)
This commit is contained in:
+135
-135
@@ -10,192 +10,192 @@
|
||||
// * Vorbis streaming playback
|
||||
|
||||
struct ChannelEffectState {
|
||||
// Filter state
|
||||
// Filter state
|
||||
};
|
||||
|
||||
enum CLIP_TYPE {
|
||||
CT_PCM16,
|
||||
CT_SYNTHFX,
|
||||
CT_VORBIS,
|
||||
// CT_PHOENIX?
|
||||
CT_PCM16,
|
||||
CT_SYNTHFX,
|
||||
CT_VORBIS,
|
||||
// CT_PHOENIX?
|
||||
};
|
||||
|
||||
struct Clip {
|
||||
int type;
|
||||
int type;
|
||||
|
||||
short *data;
|
||||
int length;
|
||||
int num_channels; // this is NOT stereo vs mono
|
||||
int sample_rate;
|
||||
int loop_start;
|
||||
int loop_end;
|
||||
short *data;
|
||||
int length;
|
||||
int num_channels; // this is NOT stereo vs mono
|
||||
int sample_rate;
|
||||
int loop_start;
|
||||
int loop_end;
|
||||
};
|
||||
|
||||
// If current_clip == 0, the channel is free.
|
||||
|
||||
enum ClipPlaybackState {
|
||||
PB_STOPPED = 0,
|
||||
PB_PLAYING = 1,
|
||||
PB_STOPPED = 0,
|
||||
PB_PLAYING = 1,
|
||||
};
|
||||
|
||||
|
||||
struct Channel {
|
||||
const Clip *current_clip;
|
||||
// Playback state
|
||||
ClipPlaybackState state;
|
||||
int pos;
|
||||
PlayParams params;
|
||||
// Effect state
|
||||
ChannelEffectState effect_state;
|
||||
const Clip *current_clip;
|
||||
// Playback state
|
||||
ClipPlaybackState state;
|
||||
int pos;
|
||||
PlayParams params;
|
||||
// Effect state
|
||||
ChannelEffectState effect_state;
|
||||
};
|
||||
|
||||
struct Mixer {
|
||||
Channel *channels;
|
||||
int sample_rate;
|
||||
int num_channels;
|
||||
int num_fixed_channels;
|
||||
Channel *channels;
|
||||
int sample_rate;
|
||||
int num_channels;
|
||||
int num_fixed_channels;
|
||||
};
|
||||
|
||||
Mixer *mixer_create(int sample_rate, int channels, int fixed_channels) {
|
||||
Mixer *mixer = new Mixer();
|
||||
memset(mixer, 0, sizeof(Mixer));
|
||||
mixer->channels = new Channel[channels];
|
||||
memset(mixer->channels, 0, sizeof(Channel) * channels);
|
||||
mixer->sample_rate = sample_rate;
|
||||
mixer->num_channels = channels;
|
||||
mixer->num_fixed_channels = fixed_channels;
|
||||
return mixer;
|
||||
Mixer *mixer = new Mixer();
|
||||
memset(mixer, 0, sizeof(Mixer));
|
||||
mixer->channels = new Channel[channels];
|
||||
memset(mixer->channels, 0, sizeof(Channel) * channels);
|
||||
mixer->sample_rate = sample_rate;
|
||||
mixer->num_channels = channels;
|
||||
mixer->num_fixed_channels = fixed_channels;
|
||||
return mixer;
|
||||
}
|
||||
|
||||
void mixer_destroy(Mixer *mixer) {
|
||||
delete [] mixer->channels;
|
||||
delete mixer;
|
||||
delete [] mixer->channels;
|
||||
delete mixer;
|
||||
}
|
||||
|
||||
static int get_free_channel(Mixer *mixer) {
|
||||
int chan_with_biggest_pos = -1;
|
||||
int biggest_pos = -1;
|
||||
for (int i = mixer->num_fixed_channels; i < mixer->num_channels; i++) {
|
||||
Channel *chan = &mixer->channels[i];
|
||||
if (!chan->current_clip) {
|
||||
return i;
|
||||
}
|
||||
if (chan->pos > biggest_pos) {
|
||||
biggest_pos = chan->pos;
|
||||
chan_with_biggest_pos = i;
|
||||
}
|
||||
}
|
||||
return chan_with_biggest_pos;
|
||||
int chan_with_biggest_pos = -1;
|
||||
int biggest_pos = -1;
|
||||
for (int i = mixer->num_fixed_channels; i < mixer->num_channels; i++) {
|
||||
Channel *chan = &mixer->channels[i];
|
||||
if (!chan->current_clip) {
|
||||
return i;
|
||||
}
|
||||
if (chan->pos > biggest_pos) {
|
||||
biggest_pos = chan->pos;
|
||||
chan_with_biggest_pos = i;
|
||||
}
|
||||
}
|
||||
return chan_with_biggest_pos;
|
||||
}
|
||||
|
||||
Clip *clip_load(const char *filename) {
|
||||
short *data;
|
||||
int num_samples;
|
||||
int sample_rate, num_channels;
|
||||
short *data;
|
||||
int num_samples;
|
||||
int sample_rate, num_channels;
|
||||
|
||||
if (!strcmp(filename + strlen(filename) - 4, ".ogg")) {
|
||||
// Ogg file. For now, directly decompress, no streaming support.
|
||||
uint8_t *filedata;
|
||||
size_t size;
|
||||
filedata = VFSReadFile(filename, &size);
|
||||
num_samples = stb_vorbis_decode_memory(filedata, size, &num_channels, &data);
|
||||
if (num_samples <= 0)
|
||||
return NULL;
|
||||
sample_rate = 44100;
|
||||
ILOG("read ogg %s, length %i, rate %i", filename, num_samples, sample_rate);
|
||||
} else {
|
||||
// Wav file. Easy peasy.
|
||||
data = wav_read(filename, &num_samples, &sample_rate, &num_channels);
|
||||
if (!data) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (!strcmp(filename + strlen(filename) - 4, ".ogg")) {
|
||||
// Ogg file. For now, directly decompress, no streaming support.
|
||||
uint8_t *filedata;
|
||||
size_t size;
|
||||
filedata = VFSReadFile(filename, &size);
|
||||
num_samples = stb_vorbis_decode_memory(filedata, size, &num_channels, &data);
|
||||
if (num_samples <= 0)
|
||||
return NULL;
|
||||
sample_rate = 44100;
|
||||
ILOG("read ogg %s, length %i, rate %i", filename, num_samples, sample_rate);
|
||||
} else {
|
||||
// Wav file. Easy peasy.
|
||||
data = wav_read(filename, &num_samples, &sample_rate, &num_channels);
|
||||
if (!data) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
Clip *clip = new Clip();
|
||||
clip->type = CT_PCM16;
|
||||
clip->data = data;
|
||||
clip->length = num_samples;
|
||||
clip->num_channels = num_channels;
|
||||
clip->sample_rate = sample_rate;
|
||||
clip->loop_start = 0;
|
||||
clip->loop_end = 0;
|
||||
return clip;
|
||||
Clip *clip = new Clip();
|
||||
clip->type = CT_PCM16;
|
||||
clip->data = data;
|
||||
clip->length = num_samples;
|
||||
clip->num_channels = num_channels;
|
||||
clip->sample_rate = sample_rate;
|
||||
clip->loop_start = 0;
|
||||
clip->loop_end = 0;
|
||||
return clip;
|
||||
}
|
||||
|
||||
void clip_destroy(Clip *clip) {
|
||||
if (clip) {
|
||||
free(clip->data);
|
||||
delete clip;
|
||||
} else {
|
||||
ELOG("Can't destroy zero clip");
|
||||
}
|
||||
if (clip) {
|
||||
free(clip->data);
|
||||
delete clip;
|
||||
} else {
|
||||
ELOG("Can't destroy zero clip");
|
||||
}
|
||||
}
|
||||
|
||||
const short *clip_data(const Clip *clip)
|
||||
{
|
||||
return clip->data;
|
||||
return clip->data;
|
||||
}
|
||||
|
||||
size_t clip_length(const Clip *clip) {
|
||||
return clip->length;
|
||||
return clip->length;
|
||||
}
|
||||
|
||||
void clip_set_loop(Clip *clip, int start, int end) {
|
||||
clip->loop_start = start;
|
||||
clip->loop_end = end;
|
||||
clip->loop_start = start;
|
||||
clip->loop_end = end;
|
||||
}
|
||||
|
||||
PlayParams *mixer_play_clip(Mixer *mixer, const Clip *clip, int channel) {
|
||||
if (channel == -1) {
|
||||
channel = get_free_channel(mixer);
|
||||
}
|
||||
if (channel == -1) {
|
||||
channel = get_free_channel(mixer);
|
||||
}
|
||||
|
||||
Channel *chan = &mixer->channels[channel];
|
||||
// Think about this order and make sure it's thread"safe" (not perfect but should not cause crashes).
|
||||
chan->pos = 0;
|
||||
chan->current_clip = clip;
|
||||
chan->state = PB_PLAYING;
|
||||
PlayParams *params = &chan->params;
|
||||
params->volume = 128;
|
||||
params->pan = 128;
|
||||
return params;
|
||||
Channel *chan = &mixer->channels[channel];
|
||||
// Think about this order and make sure it's thread"safe" (not perfect but should not cause crashes).
|
||||
chan->pos = 0;
|
||||
chan->current_clip = clip;
|
||||
chan->state = PB_PLAYING;
|
||||
PlayParams *params = &chan->params;
|
||||
params->volume = 128;
|
||||
params->pan = 128;
|
||||
return params;
|
||||
}
|
||||
|
||||
void mixer_mix(Mixer *mixer, short *buffer, int num_samples) {
|
||||
// Clear the buffer.
|
||||
memset(buffer, 0, num_samples * sizeof(short) * 2);
|
||||
for (int i = 0; i < mixer->num_channels; i++) {
|
||||
Channel *chan = &mixer->channels[i];
|
||||
if (chan->state == PB_PLAYING) {
|
||||
const Clip *clip = chan->current_clip;
|
||||
if (clip->type == CT_PCM16) {
|
||||
// For now, only allow mono PCM
|
||||
CHECK(clip->num_channels == 1);
|
||||
if (true || chan->params.delta == 0) {
|
||||
// Fast playback of non pitched clips
|
||||
int cnt = num_samples;
|
||||
if (clip->length - chan->pos < cnt) {
|
||||
cnt = clip->length - chan->pos;
|
||||
}
|
||||
// TODO: Take pan into account.
|
||||
int left_volume = chan->params.volume;
|
||||
int right_volume = chan->params.volume;
|
||||
// TODO: NEONize. Can also make special loops for left_volume == right_volume etc.
|
||||
for (int s = 0; s < cnt; s++) {
|
||||
int cdata = clip->data[chan->pos];
|
||||
buffer[s * 2 ] += cdata * left_volume >> 8;
|
||||
buffer[s * 2 + 1] += cdata * right_volume >> 8;
|
||||
chan->pos++;
|
||||
}
|
||||
if (chan->pos >= clip->length) {
|
||||
chan->state = PB_STOPPED;
|
||||
chan->current_clip = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (clip->type == CT_VORBIS) {
|
||||
// For music
|
||||
}
|
||||
}
|
||||
}
|
||||
// Clear the buffer.
|
||||
memset(buffer, 0, num_samples * sizeof(short) * 2);
|
||||
for (int i = 0; i < mixer->num_channels; i++) {
|
||||
Channel *chan = &mixer->channels[i];
|
||||
if (chan->state == PB_PLAYING) {
|
||||
const Clip *clip = chan->current_clip;
|
||||
if (clip->type == CT_PCM16) {
|
||||
// For now, only allow mono PCM
|
||||
CHECK(clip->num_channels == 1);
|
||||
if (true || chan->params.delta == 0) {
|
||||
// Fast playback of non pitched clips
|
||||
int cnt = num_samples;
|
||||
if (clip->length - chan->pos < cnt) {
|
||||
cnt = clip->length - chan->pos;
|
||||
}
|
||||
// TODO: Take pan into account.
|
||||
int left_volume = chan->params.volume;
|
||||
int right_volume = chan->params.volume;
|
||||
// TODO: NEONize. Can also make special loops for left_volume == right_volume etc.
|
||||
for (int s = 0; s < cnt; s++) {
|
||||
int cdata = clip->data[chan->pos];
|
||||
buffer[s * 2 ] += cdata * left_volume >> 8;
|
||||
buffer[s * 2 + 1] += cdata * right_volume >> 8;
|
||||
chan->pos++;
|
||||
}
|
||||
if (chan->pos >= clip->length) {
|
||||
chan->state = PB_STOPPED;
|
||||
chan->current_clip = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (clip->type == CT_VORBIS) {
|
||||
// For music
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -11,9 +11,9 @@ struct Channel;
|
||||
|
||||
// This struct is public for easy manipulation of running channels.
|
||||
struct PlayParams {
|
||||
uint8_t volume; // 0-255
|
||||
uint8_t pan; // 0-255, 127 is dead center.
|
||||
int32_t delta;
|
||||
uint8_t volume; // 0-255
|
||||
uint8_t pan; // 0-255, 127 is dead center.
|
||||
int32_t delta;
|
||||
};
|
||||
|
||||
// Mixer
|
||||
|
||||
+59
-59
@@ -4,67 +4,67 @@
|
||||
#include "file/chunk_file.h"
|
||||
|
||||
short *wav_read(const char *filename,
|
||||
int *num_samples, int *sample_rate,
|
||||
int *num_channels)
|
||||
int *num_samples, int *sample_rate,
|
||||
int *num_channels)
|
||||
{
|
||||
ChunkFile cf(filename, true);
|
||||
if (cf.failed()) {
|
||||
WLOG("ERROR: Wave file %s could not be opened", filename);
|
||||
return 0;
|
||||
}
|
||||
ChunkFile cf(filename, true);
|
||||
if (cf.failed()) {
|
||||
WLOG("ERROR: Wave file %s could not be opened", filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
short *data = 0;
|
||||
int samplesPerSec, avgBytesPerSec,wBlockAlign,wBytesPerSample;
|
||||
if (cf.descend('RIFF')) {
|
||||
cf.readInt(); //get past 'WAVE'
|
||||
if (cf.descend('fmt ')) { //enter the format chunk
|
||||
int temp = cf.readInt();
|
||||
int format = temp & 0xFFFF;
|
||||
if (format != 1) {
|
||||
cf.ascend();
|
||||
cf.ascend();
|
||||
ELOG("Error - bad format");
|
||||
return NULL;
|
||||
}
|
||||
*num_channels = temp >> 16;
|
||||
samplesPerSec = cf.readInt();
|
||||
avgBytesPerSec = cf.readInt();
|
||||
short *data = 0;
|
||||
int samplesPerSec, avgBytesPerSec,wBlockAlign,wBytesPerSample;
|
||||
if (cf.descend('RIFF')) {
|
||||
cf.readInt(); //get past 'WAVE'
|
||||
if (cf.descend('fmt ')) { //enter the format chunk
|
||||
int temp = cf.readInt();
|
||||
int format = temp & 0xFFFF;
|
||||
if (format != 1) {
|
||||
cf.ascend();
|
||||
cf.ascend();
|
||||
ELOG("Error - bad format");
|
||||
return NULL;
|
||||
}
|
||||
*num_channels = temp >> 16;
|
||||
samplesPerSec = cf.readInt();
|
||||
avgBytesPerSec = cf.readInt();
|
||||
|
||||
temp = cf.readInt();
|
||||
wBlockAlign = temp & 0xFFFF;
|
||||
wBytesPerSample = temp >> 16;
|
||||
cf.ascend();
|
||||
// ILOG("got fmt data: %i", samplesPerSec);
|
||||
} else {
|
||||
ELOG("Error - no format chunk in wav");
|
||||
cf.ascend();
|
||||
return NULL;
|
||||
}
|
||||
temp = cf.readInt();
|
||||
wBlockAlign = temp & 0xFFFF;
|
||||
wBytesPerSample = temp >> 16;
|
||||
cf.ascend();
|
||||
// ILOG("got fmt data: %i", samplesPerSec);
|
||||
} else {
|
||||
ELOG("Error - no format chunk in wav");
|
||||
cf.ascend();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (cf.descend('data')) { //enter the data chunk
|
||||
int numBytes = cf.getCurrentChunkSize();
|
||||
int numSamples = numBytes / wBlockAlign;
|
||||
data = (short *)malloc(sizeof(short) * numSamples * *num_channels);
|
||||
*num_samples = numSamples;
|
||||
if (wBlockAlign == 2 && *num_channels == 1) {
|
||||
cf.readData((uint8*)data,numBytes);
|
||||
} else {
|
||||
ELOG("Error - bad blockalign or channels");
|
||||
free(data);
|
||||
return NULL;
|
||||
}
|
||||
cf.ascend();
|
||||
} else {
|
||||
ELOG("Error - no data chunk in wav");
|
||||
cf.ascend();
|
||||
return NULL;
|
||||
}
|
||||
cf.ascend();
|
||||
} else {
|
||||
ELOG("Could not descend into RIFF file");
|
||||
return NULL;
|
||||
}
|
||||
*sample_rate = samplesPerSec;
|
||||
ILOG("read wav %s, length %i, rate %i", filename, *num_samples, *sample_rate);
|
||||
return data;
|
||||
if (cf.descend('data')) { //enter the data chunk
|
||||
int numBytes = cf.getCurrentChunkSize();
|
||||
int numSamples = numBytes / wBlockAlign;
|
||||
data = (short *)malloc(sizeof(short) * numSamples * *num_channels);
|
||||
*num_samples = numSamples;
|
||||
if (wBlockAlign == 2 && *num_channels == 1) {
|
||||
cf.readData((uint8*)data,numBytes);
|
||||
} else {
|
||||
ELOG("Error - bad blockalign or channels");
|
||||
free(data);
|
||||
return NULL;
|
||||
}
|
||||
cf.ascend();
|
||||
} else {
|
||||
ELOG("Error - no data chunk in wav");
|
||||
cf.ascend();
|
||||
return NULL;
|
||||
}
|
||||
cf.ascend();
|
||||
} else {
|
||||
ELOG("Could not descend into RIFF file");
|
||||
return NULL;
|
||||
}
|
||||
*sample_rate = samplesPerSec;
|
||||
ILOG("read wav %s, length %i, rate %i", filename, *num_samples, *sample_rate);
|
||||
return data;
|
||||
}
|
||||
|
||||
+2
-2
@@ -2,6 +2,6 @@
|
||||
|
||||
// Allocates a buffer that should be freed using free().
|
||||
short *wav_read(const char *filename,
|
||||
int *num_samples, int *sample_rate,
|
||||
int *num_channels);
|
||||
int *num_samples, int *sample_rate,
|
||||
int *num_channels);
|
||||
// TODO: Non-allocating version.
|
||||
|
||||
+3
-3
@@ -10,8 +10,8 @@
|
||||
static void *backtrace_buffer[128];
|
||||
|
||||
void PrintBacktraceToStderr() {
|
||||
int num_addrs = backtrace(backtrace_buffer, 128);
|
||||
backtrace_symbols_fd(backtrace_buffer, num_addrs, STDERR_FILENO);
|
||||
int num_addrs = backtrace(backtrace_buffer, 128);
|
||||
backtrace_symbols_fd(backtrace_buffer, num_addrs, STDERR_FILENO);
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@
|
||||
#endif
|
||||
|
||||
#define DISALLOW_COPY_AND_ASSIGN(t) \
|
||||
private: \
|
||||
private: \
|
||||
t(const t &other); \
|
||||
void operator =(const t &other);
|
||||
|
||||
|
||||
+59
-59
@@ -1,45 +1,45 @@
|
||||
#include "base/colorutil.h"
|
||||
|
||||
uint32_t whiteAlpha(float alpha) {
|
||||
if (alpha < 0.0f) alpha = 0.0f;
|
||||
if (alpha > 1.0f) alpha = 1.0f;
|
||||
uint32_t color = (int)(alpha*255) << 24;
|
||||
color |= 0xFFFFFF;
|
||||
return color;
|
||||
if (alpha < 0.0f) alpha = 0.0f;
|
||||
if (alpha > 1.0f) alpha = 1.0f;
|
||||
uint32_t color = (int)(alpha*255) << 24;
|
||||
color |= 0xFFFFFF;
|
||||
return color;
|
||||
}
|
||||
|
||||
uint32_t blackAlpha(float alpha) {
|
||||
if (alpha < 0.0f) alpha = 0.0f;
|
||||
if (alpha > 1.0f) alpha = 1.0f;
|
||||
return (int)(alpha*255)<<24;
|
||||
if (alpha < 0.0f) alpha = 0.0f;
|
||||
if (alpha > 1.0f) alpha = 1.0f;
|
||||
return (int)(alpha*255)<<24;
|
||||
}
|
||||
|
||||
uint32_t colorAlpha(uint32_t color, float alpha) {
|
||||
if (alpha < 0.0f) alpha = 0.0f;
|
||||
if (alpha > 1.0f) alpha = 1.0f;
|
||||
return ((int)(alpha*255)<<24) | (color & 0xFFFFFF);
|
||||
if (alpha < 0.0f) alpha = 0.0f;
|
||||
if (alpha > 1.0f) alpha = 1.0f;
|
||||
return ((int)(alpha*255)<<24) | (color & 0xFFFFFF);
|
||||
}
|
||||
|
||||
uint32_t rgba(float r, float g, float b, float alpha) {
|
||||
uint32_t color = (int)(alpha*255)<<24;
|
||||
color |= (int)(b*255)<<16;
|
||||
color |= (int)(g*255)<<8;
|
||||
color |= (int)(r*255);
|
||||
return color;
|
||||
uint32_t color = (int)(alpha*255)<<24;
|
||||
color |= (int)(b*255)<<16;
|
||||
color |= (int)(g*255)<<8;
|
||||
color |= (int)(r*255);
|
||||
return color;
|
||||
}
|
||||
|
||||
uint32_t rgba_clamp(float r, float g, float b, float a) {
|
||||
if (r > 1.0f) r = 1.0f;
|
||||
if (g > 1.0f) g = 1.0f;
|
||||
if (b > 1.0f) b = 1.0f;
|
||||
if (a > 1.0f) a = 1.0f;
|
||||
if (r > 1.0f) r = 1.0f;
|
||||
if (g > 1.0f) g = 1.0f;
|
||||
if (b > 1.0f) b = 1.0f;
|
||||
if (a > 1.0f) a = 1.0f;
|
||||
|
||||
if (r < 0.0f) r = 0.0f;
|
||||
if (g < 0.0f) g = 0.0f;
|
||||
if (b < 0.0f) b = 0.0f;
|
||||
if (a < 0.0f) a = 0.0f;
|
||||
if (r < 0.0f) r = 0.0f;
|
||||
if (g < 0.0f) g = 0.0f;
|
||||
if (b < 0.0f) b = 0.0f;
|
||||
if (a < 0.0f) a = 0.0f;
|
||||
|
||||
return rgba(r,g,b,a);
|
||||
return rgba(r,g,b,a);
|
||||
}
|
||||
|
||||
/* hsv2rgb.c
|
||||
@@ -53,40 +53,40 @@ uint32_t rgba_clamp(float r, float g, float b, float a) {
|
||||
* McGraw Hill 1985
|
||||
*/
|
||||
uint32_t hsva(float H, float S, float V, float alpha) {
|
||||
/*
|
||||
* Purpose:
|
||||
* Convert HSV values to RGB values
|
||||
* All values are in the range [0.0 .. 1.0]
|
||||
*/
|
||||
float F, M, N, K;
|
||||
int I;
|
||||
if ( S == 0.0 ) {
|
||||
// Achromatic case, set level of grey
|
||||
return rgba(V, V, V, alpha);
|
||||
} else {
|
||||
/*
|
||||
* Determine levels of primary colours.
|
||||
*/
|
||||
if (H >= 1.0) {
|
||||
H = 0.0;
|
||||
} else {
|
||||
H = H * 6;
|
||||
}
|
||||
I = (int) H; /* should be in the range 0..5 */
|
||||
F = H - I; /* fractional part */
|
||||
/*
|
||||
* Purpose:
|
||||
* Convert HSV values to RGB values
|
||||
* All values are in the range [0.0 .. 1.0]
|
||||
*/
|
||||
float F, M, N, K;
|
||||
int I;
|
||||
if ( S == 0.0 ) {
|
||||
// Achromatic case, set level of grey
|
||||
return rgba(V, V, V, alpha);
|
||||
} else {
|
||||
/*
|
||||
* Determine levels of primary colours.
|
||||
*/
|
||||
if (H >= 1.0) {
|
||||
H = 0.0;
|
||||
} else {
|
||||
H = H * 6;
|
||||
}
|
||||
I = (int) H; /* should be in the range 0..5 */
|
||||
F = H - I; /* fractional part */
|
||||
|
||||
M = V * (1 - S);
|
||||
N = V * (1 - S * F);
|
||||
K = V * (1 - S * (1 - F));
|
||||
M = V * (1 - S);
|
||||
N = V * (1 - S * F);
|
||||
K = V * (1 - S * (1 - F));
|
||||
|
||||
float r, g, b;
|
||||
if (I == 0) { r = V; g = K; b = M; }
|
||||
else if (I == 1) { r = N; g = V; b = M; }
|
||||
else if (I == 2) { r = M; g = V; b = K; }
|
||||
else if (I == 3) { r = M; g = N; b = V; }
|
||||
else if (I == 4) { r = K; g = M; b = V; }
|
||||
else if (I == 5) { r = V; g = M; b = N; }
|
||||
else return 0;
|
||||
return rgba(r, g, b, alpha);
|
||||
}
|
||||
float r, g, b;
|
||||
if (I == 0) { r = V; g = K; b = M; }
|
||||
else if (I == 1) { r = N; g = V; b = M; }
|
||||
else if (I == 2) { r = M; g = V; b = K; }
|
||||
else if (I == 3) { r = M; g = N; b = V; }
|
||||
else if (I == 4) { r = K; g = M; b = V; }
|
||||
else if (I == 5) { r = V; g = M; b = N; }
|
||||
else return 0;
|
||||
return rgba(r, g, b, alpha);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,10 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "base/basictypes.h"
|
||||
|
||||
|
||||
uint32_t whiteAlpha(float alpha);
|
||||
uint32_t blackAlpha(float alpha);
|
||||
uint32_t colorAlpha(uint32_t color, float alpha);
|
||||
uint32_t rgba(float r, float g, float b, float alpha);
|
||||
uint32_t rgba_clamp(float r, float g, float b, float alpha);
|
||||
uint32_t hsva(float h, float s, float v, float alpha);
|
||||
uint32_t hsva(float h, float s, float v, float alpha);
|
||||
|
||||
+18
-18
@@ -13,28 +13,28 @@ __THREAD std::vector<const char *> *_error_context_name;
|
||||
__THREAD std::vector<const char *> *_error_context_data;
|
||||
|
||||
_ErrorContext::_ErrorContext(const char *name, const char *data) {
|
||||
if (!_error_context_name) {
|
||||
_error_context_name = new std::vector<const char *>();
|
||||
_error_context_data = new std::vector<const char *>();
|
||||
_error_context_name->reserve(16);
|
||||
_error_context_data->reserve(16);
|
||||
}
|
||||
_error_context_name->push_back(name);
|
||||
_error_context_data->push_back(data);
|
||||
if (!_error_context_name) {
|
||||
_error_context_name = new std::vector<const char *>();
|
||||
_error_context_data = new std::vector<const char *>();
|
||||
_error_context_name->reserve(16);
|
||||
_error_context_data->reserve(16);
|
||||
}
|
||||
_error_context_name->push_back(name);
|
||||
_error_context_data->push_back(data);
|
||||
}
|
||||
|
||||
_ErrorContext::~_ErrorContext() {
|
||||
_error_context_name->pop_back();
|
||||
_error_context_data->pop_back();
|
||||
_error_context_name->pop_back();
|
||||
_error_context_data->pop_back();
|
||||
}
|
||||
|
||||
void _ErrorContext::Log(const char *message) {
|
||||
ILOG("EC: %s", message);
|
||||
for (size_t i = 0; i < _error_context_name->size(); i++) {
|
||||
if ((*_error_context_data)[i] != 0) {
|
||||
ILOG("EC: %s: %s", (*_error_context_name)[i], (*_error_context_data)[i]);
|
||||
} else {
|
||||
ILOG("EC: %s: %s", (*_error_context_name)[i], (*_error_context_data)[i]);
|
||||
}
|
||||
}
|
||||
ILOG("EC: %s", message);
|
||||
for (size_t i = 0; i < _error_context_name->size(); i++) {
|
||||
if ((*_error_context_data)[i] != 0) {
|
||||
ILOG("EC: %s: %s", (*_error_context_name)[i], (*_error_context_data)[i]);
|
||||
} else {
|
||||
ILOG("EC: %s: %s", (*_error_context_name)[i], (*_error_context_data)[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,12 +7,12 @@
|
||||
class _ErrorContext
|
||||
{
|
||||
public:
|
||||
_ErrorContext(const char *name, const char *data = 0);
|
||||
~_ErrorContext();
|
||||
_ErrorContext(const char *name, const char *data = 0);
|
||||
~_ErrorContext();
|
||||
|
||||
// Logs the current context stack.
|
||||
static void Log(const char *message);
|
||||
// Logs the current context stack.
|
||||
static void Log(const char *message);
|
||||
};
|
||||
|
||||
#define ErrorContext(...) _ErrorContext __ec(__VA_ARGS__)
|
||||
#define LogErrorContext(msg) _ErrorContext::Log(msg)
|
||||
#define LogErrorContext(msg) _ErrorContext::Log(msg)
|
||||
|
||||
+25
-25
@@ -7,33 +7,33 @@
|
||||
// Order is not preserved when removing objects.
|
||||
template<class T, int max_size>
|
||||
class InlineFastList {
|
||||
public:
|
||||
InlineFastList() : count_(0) {}
|
||||
~InlineFastList() {}
|
||||
public:
|
||||
InlineFastList() : count_(0) {}
|
||||
~InlineFastList() {}
|
||||
|
||||
T& operator [](int index) { return data_[index]; }
|
||||
const T& operator [](int index) const { return data_[index]; }
|
||||
int size() const { return count_; }
|
||||
|
||||
void Add(T t) {
|
||||
data_[count_++] = t;
|
||||
}
|
||||
T& operator [](int index) { return data_[index]; }
|
||||
const T& operator [](int index) const { return data_[index]; }
|
||||
int size() const { return count_; }
|
||||
|
||||
void RemoveAt(int index) {
|
||||
data_[index] = data_[count_ - 1];
|
||||
count_--;
|
||||
}
|
||||
void Add(T t) {
|
||||
data_[count_++] = t;
|
||||
}
|
||||
|
||||
void Remove(T t) { // Requires operator==
|
||||
for (int i = 0; i < count_; i++) {
|
||||
if (data_[i] == t) {
|
||||
RemoveAt(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
void RemoveAt(int index) {
|
||||
data_[index] = data_[count_ - 1];
|
||||
count_--;
|
||||
}
|
||||
|
||||
private:
|
||||
T data_[max_size];
|
||||
int count_;
|
||||
void Remove(T t) { // Requires operator==
|
||||
for (int i = 0; i < count_; i++) {
|
||||
if (data_[i] == t) {
|
||||
RemoveAt(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
T data_[max_size];
|
||||
int count_;
|
||||
};
|
||||
|
||||
+36
-36
@@ -14,47 +14,47 @@
|
||||
template <class X> class linked_ptr
|
||||
{
|
||||
public:
|
||||
explicit linked_ptr(X* p = 0) throw() : itsPtr(p) {itsPrev = itsNext = this;}
|
||||
~linked_ptr() {release();}
|
||||
linked_ptr(const linked_ptr& r) throw() {acquire(r);}
|
||||
explicit linked_ptr(X* p = 0) throw() : itsPtr(p) {itsPrev = itsNext = this;}
|
||||
~linked_ptr() {release();}
|
||||
linked_ptr(const linked_ptr& r) throw() {acquire(r);}
|
||||
|
||||
linked_ptr& operator=(const linked_ptr& r)
|
||||
{
|
||||
if (this != &r) {
|
||||
release();
|
||||
acquire(r);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
linked_ptr& operator=(const linked_ptr& r)
|
||||
{
|
||||
if (this != &r) {
|
||||
release();
|
||||
acquire(r);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
X& operator*() const throw() {return *itsPtr;}
|
||||
X* operator->() const throw() {return itsPtr;}
|
||||
X* get() const throw() {return itsPtr;}
|
||||
bool unique() const throw() {return itsPrev ? itsPrev==this : true;}
|
||||
X& operator*() const throw() {return *itsPtr;}
|
||||
X* operator->() const throw() {return itsPtr;}
|
||||
X* get() const throw() {return itsPtr;}
|
||||
bool unique() const throw() {return itsPrev ? itsPrev==this : true;}
|
||||
|
||||
private:
|
||||
X* itsPtr;
|
||||
mutable const linked_ptr* itsPrev;
|
||||
mutable const linked_ptr* itsNext;
|
||||
X* itsPtr;
|
||||
mutable const linked_ptr* itsPrev;
|
||||
mutable const linked_ptr* itsNext;
|
||||
|
||||
void acquire(const linked_ptr& r) throw()
|
||||
{ // insert this to the list
|
||||
itsPtr = r.itsPtr;
|
||||
itsNext = r.itsNext;
|
||||
itsNext->itsPrev = this;
|
||||
itsPrev = &r;
|
||||
r.itsNext = this;
|
||||
}
|
||||
void acquire(const linked_ptr& r) throw()
|
||||
{ // insert this to the list
|
||||
itsPtr = r.itsPtr;
|
||||
itsNext = r.itsNext;
|
||||
itsNext->itsPrev = this;
|
||||
itsPrev = &r;
|
||||
r.itsNext = this;
|
||||
}
|
||||
|
||||
void release()
|
||||
{ // erase this from the list, delete if unique
|
||||
if (unique()) delete itsPtr;
|
||||
else {
|
||||
itsPrev->itsNext = itsNext;
|
||||
itsNext->itsPrev = itsPrev;
|
||||
itsPrev = itsNext = 0;
|
||||
}
|
||||
itsPtr = 0;
|
||||
}
|
||||
void release()
|
||||
{ // erase this from the list, delete if unique
|
||||
if (unique()) delete itsPtr;
|
||||
else {
|
||||
itsPrev->itsNext = itsNext;
|
||||
itsNext->itsPrev = itsPrev;
|
||||
itsPrev = itsNext = 0;
|
||||
}
|
||||
itsPtr = 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+19
-19
@@ -5,25 +5,25 @@
|
||||
template<class T>
|
||||
class scoped_ptr {
|
||||
public:
|
||||
scoped_ptr() : ptr_(0) {}
|
||||
scoped_ptr(T *p) : ptr_(p) {}
|
||||
~scoped_ptr() {
|
||||
delete ptr_;
|
||||
}
|
||||
void reset(T *p) {
|
||||
delete ptr_;
|
||||
ptr_ = p;
|
||||
}
|
||||
T *release() {
|
||||
T *p = ptr_;
|
||||
ptr_ = 0;
|
||||
return p;
|
||||
}
|
||||
T *operator->() { return ptr_; }
|
||||
const T *operator->() const { return ptr_; }
|
||||
scoped_ptr() : ptr_(0) {}
|
||||
scoped_ptr(T *p) : ptr_(p) {}
|
||||
~scoped_ptr() {
|
||||
delete ptr_;
|
||||
}
|
||||
void reset(T *p) {
|
||||
delete ptr_;
|
||||
ptr_ = p;
|
||||
}
|
||||
T *release() {
|
||||
T *p = ptr_;
|
||||
ptr_ = 0;
|
||||
return p;
|
||||
}
|
||||
T *operator->() { return ptr_; }
|
||||
const T *operator->() const { return ptr_; }
|
||||
|
||||
private:
|
||||
scoped_ptr(const scoped_ptr<T> &other);
|
||||
void operator=(const scoped_ptr<T> &other);
|
||||
T *ptr_;
|
||||
scoped_ptr(const scoped_ptr<T> &other);
|
||||
void operator=(const scoped_ptr<T> &other);
|
||||
T *ptr_;
|
||||
};
|
||||
|
||||
+9
-9
@@ -34,7 +34,7 @@ unsigned int parseHex(const char *_szValue)
|
||||
case 'e': Value += 14; break;
|
||||
case 'F': Value += 15; break;
|
||||
case 'f': Value += 15; break;
|
||||
default:
|
||||
default:
|
||||
Value = (Value >> 4);
|
||||
Count = Finish;
|
||||
}
|
||||
@@ -43,11 +43,11 @@ unsigned int parseHex(const char *_szValue)
|
||||
}
|
||||
|
||||
void DataToHexString(const uint8 *data, size_t size, std::string *output) {
|
||||
Buffer buffer;
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
buffer.Printf("%02x ", data[i]);
|
||||
if (i && !(i & 15))
|
||||
buffer.Printf("\n");
|
||||
}
|
||||
buffer.TakeAll(output);
|
||||
}
|
||||
Buffer buffer;
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
buffer.Printf("%02x ", data[i]);
|
||||
if (i && !(i & 15))
|
||||
buffer.Printf("\n");
|
||||
}
|
||||
buffer.TakeAll(output);
|
||||
}
|
||||
|
||||
+8
-8
@@ -22,17 +22,17 @@ void setCurrentThreadName(const char *name);
|
||||
class thread {
|
||||
private:
|
||||
#ifdef _WIN32
|
||||
typedef HANDLE thread_;
|
||||
typedef HANDLE thread_;
|
||||
#else
|
||||
typedef pthread_t thread_;
|
||||
typedef pthread_t thread_;
|
||||
#endif
|
||||
|
||||
public:
|
||||
//void run(std::function<void()> threadFunc) {
|
||||
// func_ =
|
||||
//}
|
||||
//void run(std::function<void()> threadFunc) {
|
||||
// func_ =
|
||||
//}
|
||||
|
||||
void wait() {
|
||||
void wait() {
|
||||
|
||||
}
|
||||
};*/
|
||||
}
|
||||
};*/
|
||||
|
||||
+30
-30
@@ -18,63 +18,63 @@ __int64 _frequency = 0;
|
||||
__int64 _starttime = 0;
|
||||
|
||||
double real_time_now(){
|
||||
if (_frequency == 0) {
|
||||
QueryPerformanceFrequency((LARGE_INTEGER*)&_frequency);
|
||||
QueryPerformanceCounter((LARGE_INTEGER*)&_starttime);
|
||||
curtime=0;
|
||||
}
|
||||
__int64 time;
|
||||
QueryPerformanceCounter((LARGE_INTEGER*)&time);
|
||||
return ((double) (time - _starttime) / (double) _frequency);
|
||||
if (_frequency == 0) {
|
||||
QueryPerformanceFrequency((LARGE_INTEGER*)&_frequency);
|
||||
QueryPerformanceCounter((LARGE_INTEGER*)&_starttime);
|
||||
curtime=0;
|
||||
}
|
||||
__int64 time;
|
||||
QueryPerformanceCounter((LARGE_INTEGER*)&time);
|
||||
return ((double) (time - _starttime) / (double) _frequency);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
double real_time_now() {
|
||||
static time_t start;
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
if (start == 0) {
|
||||
start = tv.tv_sec;
|
||||
}
|
||||
tv.tv_sec -= start;
|
||||
return (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0;
|
||||
static time_t start;
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
if (start == 0) {
|
||||
start = tv.tv_sec;
|
||||
}
|
||||
tv.tv_sec -= start;
|
||||
return (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void time_update() {
|
||||
curtime = real_time_now();
|
||||
curtime_f = (float)curtime;
|
||||
curtime = real_time_now();
|
||||
curtime_f = (float)curtime;
|
||||
|
||||
//printf("curtime: %f %f\n", curtime, curtime_f);
|
||||
// also smooth time.
|
||||
//curtime+=float((double) (time-_starttime) / (double) _frequency);
|
||||
//curtime*=0.5f;
|
||||
//curtime+=1.0f/60.0f;
|
||||
//lastTime=curtime;
|
||||
//curtime_f = (float)curtime;
|
||||
//printf("curtime: %f %f\n", curtime, curtime_f);
|
||||
// also smooth time.
|
||||
//curtime+=float((double) (time-_starttime) / (double) _frequency);
|
||||
//curtime*=0.5f;
|
||||
//curtime+=1.0f/60.0f;
|
||||
//lastTime=curtime;
|
||||
//curtime_f = (float)curtime;
|
||||
}
|
||||
|
||||
float time_now() {
|
||||
return curtime_f;
|
||||
return curtime_f;
|
||||
}
|
||||
|
||||
double time_now_d() {
|
||||
return curtime;
|
||||
return curtime;
|
||||
}
|
||||
|
||||
int time_now_ms() {
|
||||
return int(curtime*1000.0);
|
||||
return int(curtime*1000.0);
|
||||
}
|
||||
|
||||
void sleep_ms(int ms) {
|
||||
#ifdef _WIN32
|
||||
#ifndef METRO
|
||||
Sleep(ms);
|
||||
Sleep(ms);
|
||||
#endif
|
||||
#else
|
||||
usleep(ms * 1000);
|
||||
usleep(ms * 1000);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
+35
-35
@@ -14,43 +14,43 @@ typedef char GLchar;
|
||||
#include "base/logging.h"
|
||||
|
||||
void glCheckzor(const char *file, int line) {
|
||||
GLenum err = glGetError();
|
||||
if (err != GL_NO_ERROR) {
|
||||
ELOG("GL error on line %i in %s: %i (%04x)", line, file, (int)err, (int)err);
|
||||
}
|
||||
GLenum err = glGetError();
|
||||
if (err != GL_NO_ERROR) {
|
||||
ELOG("GL error on line %i in %s: %i (%04x)", line, file, (int)err, (int)err);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef ANDROID
|
||||
#if 0
|
||||
void log_callback(GLenum source, GLenum type,
|
||||
GLuint id,
|
||||
GLenum severity,
|
||||
GLsizei length,
|
||||
const GLchar* message,
|
||||
GLvoid* userParam) {
|
||||
const char *src = "unknown";
|
||||
switch (source) {
|
||||
case GL_DEBUG_SOURCE_API_GL_ARB:
|
||||
src = "GL";
|
||||
break;
|
||||
case GL_DEBUG_SOURCE_SHADER_COMPILER_ARB:
|
||||
src = "GLSL";
|
||||
break;
|
||||
case GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB:
|
||||
src = "X";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch (type) {
|
||||
case GL_DEBUG_TYPE_ERROR_ARB:
|
||||
case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB:
|
||||
ELOG("%s: %s", src, message);
|
||||
break;
|
||||
default:
|
||||
ILOG("%s: %s", src, message);
|
||||
break;
|
||||
}
|
||||
GLuint id,
|
||||
GLenum severity,
|
||||
GLsizei length,
|
||||
const GLchar* message,
|
||||
GLvoid* userParam) {
|
||||
const char *src = "unknown";
|
||||
switch (source) {
|
||||
case GL_DEBUG_SOURCE_API_GL_ARB:
|
||||
src = "GL";
|
||||
break;
|
||||
case GL_DEBUG_SOURCE_SHADER_COMPILER_ARB:
|
||||
src = "GLSL";
|
||||
break;
|
||||
case GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB:
|
||||
src = "X";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch (type) {
|
||||
case GL_DEBUG_TYPE_ERROR_ARB:
|
||||
case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB:
|
||||
ELOG("%s: %s", src, message);
|
||||
break;
|
||||
default:
|
||||
ILOG("%s: %s", src, message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -58,9 +58,9 @@ void log_callback(GLenum source, GLenum type,
|
||||
void gl_log_enable() {
|
||||
#ifndef ANDROID
|
||||
#if 0
|
||||
glEnable(DEBUG_OUTPUT_SYNCHRONOUS_ARB); // TODO: Look into disabling, for more perf
|
||||
glDebugMessageCallback(&log_callback, 0);
|
||||
glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, 0, GL_TRUE);
|
||||
glEnable(DEBUG_OUTPUT_SYNCHRONOUS_ARB); // TODO: Look into disabling, for more perf
|
||||
glDebugMessageCallback(&log_callback, 0);
|
||||
glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, 0, GL_TRUE);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
+26
-27
@@ -8,42 +8,41 @@ std::list<GfxResourceHolder *> *holders;
|
||||
GfxResourceHolder::~GfxResourceHolder() {}
|
||||
|
||||
void register_gl_resource_holder(GfxResourceHolder *holder) {
|
||||
if (holders) {
|
||||
holders->push_back(holder);
|
||||
} else {
|
||||
WLOG("GL resource holder not initialized, cannot register resource");
|
||||
}
|
||||
if (holders) {
|
||||
holders->push_back(holder);
|
||||
} else {
|
||||
WLOG("GL resource holder not initialized, cannot register resource");
|
||||
}
|
||||
}
|
||||
void unregister_gl_resource_holder(GfxResourceHolder *holder) {
|
||||
if (holders) {
|
||||
holders->remove(holder);
|
||||
} else {
|
||||
WLOG("GL resource holder not initialized or already shutdown, cannot unregister resource");
|
||||
}
|
||||
if (holders) {
|
||||
holders->remove(holder);
|
||||
} else {
|
||||
WLOG("GL resource holder not initialized or already shutdown, cannot unregister resource");
|
||||
}
|
||||
}
|
||||
|
||||
void gl_lost() {
|
||||
if (!holders) {
|
||||
WLOG("GL resource holder not initialized, cannot process lost request");
|
||||
return;
|
||||
}
|
||||
for (std::list<GfxResourceHolder *>::iterator iter = holders->begin();
|
||||
iter != holders->end(); ++iter) {
|
||||
(*iter)->GLLost();
|
||||
}
|
||||
if (!holders) {
|
||||
WLOG("GL resource holder not initialized, cannot process lost request");
|
||||
return;
|
||||
}
|
||||
for (std::list<GfxResourceHolder *>::iterator iter = holders->begin(); iter != holders->end(); ++iter) {
|
||||
(*iter)->GLLost();
|
||||
}
|
||||
}
|
||||
|
||||
void gl_lost_manager_init() {
|
||||
if (holders) {
|
||||
FLOG("Double GL lost manager init");
|
||||
}
|
||||
holders = new std::list<GfxResourceHolder *>();
|
||||
if (holders) {
|
||||
FLOG("Double GL lost manager init");
|
||||
}
|
||||
holders = new std::list<GfxResourceHolder *>();
|
||||
}
|
||||
|
||||
void gl_lost_manager_shutdown() {
|
||||
if (!holders) {
|
||||
FLOG("Lost manager already shutdown");
|
||||
}
|
||||
delete holders;
|
||||
holders = 0;
|
||||
if (!holders) {
|
||||
FLOG("Lost manager already shutdown");
|
||||
}
|
||||
delete holders;
|
||||
holders = 0;
|
||||
}
|
||||
|
||||
+197
-197
@@ -27,160 +27,160 @@
|
||||
#include "gfx/gl_lost_manager.h"
|
||||
|
||||
Texture::Texture() : id_(0) {
|
||||
register_gl_resource_holder(this);
|
||||
register_gl_resource_holder(this);
|
||||
}
|
||||
|
||||
void Texture::Destroy() {
|
||||
if (id_) {
|
||||
glDeleteTextures(1, &id_);
|
||||
id_ = 0;
|
||||
}
|
||||
if (id_) {
|
||||
glDeleteTextures(1, &id_);
|
||||
id_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Texture::GLLost() {
|
||||
ILOG("Reloading lost texture %s", filename_.c_str());
|
||||
Load(filename_.c_str());
|
||||
ILOG("Reloading lost texture %s", filename_.c_str());
|
||||
Load(filename_.c_str());
|
||||
}
|
||||
|
||||
Texture::~Texture() {
|
||||
unregister_gl_resource_holder(this);
|
||||
Destroy();
|
||||
unregister_gl_resource_holder(this);
|
||||
Destroy();
|
||||
}
|
||||
|
||||
static void SetTextureParameters(int zim_flags) {
|
||||
GLenum wrap = GL_REPEAT;
|
||||
if (zim_flags & ZIM_CLAMP) wrap = GL_CLAMP_TO_EDGE;
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap);
|
||||
GL_CHECK();
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
if ((zim_flags & (ZIM_HAS_MIPS | ZIM_GEN_MIPS))) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
|
||||
} else {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
}
|
||||
GL_CHECK();
|
||||
GLenum wrap = GL_REPEAT;
|
||||
if (zim_flags & ZIM_CLAMP) wrap = GL_CLAMP_TO_EDGE;
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap);
|
||||
GL_CHECK();
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
if ((zim_flags & (ZIM_HAS_MIPS | ZIM_GEN_MIPS))) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
|
||||
} else {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
}
|
||||
GL_CHECK();
|
||||
}
|
||||
|
||||
bool Texture::Load(const char *filename) {
|
||||
// hook for generated textures
|
||||
if (!memcmp(filename, "gen:", 4)) {
|
||||
// TODO
|
||||
// return false;
|
||||
int bpp, w, h;
|
||||
bool clamp;
|
||||
uint8_t *data = generateTexture(filename, bpp, w, h, clamp);
|
||||
if (!data)
|
||||
return false;
|
||||
glGenTextures(1, &id_);
|
||||
glBindTexture(GL_TEXTURE_2D, id_);
|
||||
if (bpp == 1) {
|
||||
// hook for generated textures
|
||||
if (!memcmp(filename, "gen:", 4)) {
|
||||
// TODO
|
||||
// return false;
|
||||
int bpp, w, h;
|
||||
bool clamp;
|
||||
uint8_t *data = generateTexture(filename, bpp, w, h, clamp);
|
||||
if (!data)
|
||||
return false;
|
||||
glGenTextures(1, &id_);
|
||||
glBindTexture(GL_TEXTURE_2D, id_);
|
||||
if (bpp == 1) {
|
||||
|
||||
#ifdef ANDROID
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, w, h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, w, h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
|
||||
#else
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, 1, w, h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, 1, w, h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
|
||||
#endif
|
||||
} else {
|
||||
FLOG("unsupported");
|
||||
}
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
delete [] data;
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
FLOG("unsupported");
|
||||
}
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
delete [] data;
|
||||
return true;
|
||||
}
|
||||
|
||||
filename_ = filename;
|
||||
filename_ = filename;
|
||||
|
||||
// Currently here are a bunch of project-specific workarounds.
|
||||
// They shouldn't really hurt anything else very much though.
|
||||
// Currently here are a bunch of project-specific workarounds.
|
||||
// They shouldn't really hurt anything else very much though.
|
||||
|
||||
int len = strlen(filename);
|
||||
char fn[256];
|
||||
strcpy(fn, filename);
|
||||
bool zim = false;
|
||||
if (!strcmp("dds", &filename[len-3])) {
|
||||
strcpy(&fn[len-3], "zim");
|
||||
zim = true;
|
||||
}
|
||||
if (!strcmp("6TX", &filename[len-3]) || !strcmp("6tx", &filename[len-3])) {
|
||||
ILOG("Detected 6TX %s", filename);
|
||||
strcpy(&fn[len-3], "zim");
|
||||
zim = true;
|
||||
}
|
||||
for (int i = 0; i < (int)strlen(fn); i++) {
|
||||
if (fn[i] == '\\') fn[i] = '/';
|
||||
}
|
||||
int len = strlen(filename);
|
||||
char fn[256];
|
||||
strcpy(fn, filename);
|
||||
bool zim = false;
|
||||
if (!strcmp("dds", &filename[len-3])) {
|
||||
strcpy(&fn[len-3], "zim");
|
||||
zim = true;
|
||||
}
|
||||
if (!strcmp("6TX", &filename[len-3]) || !strcmp("6tx", &filename[len-3])) {
|
||||
ILOG("Detected 6TX %s", filename);
|
||||
strcpy(&fn[len-3], "zim");
|
||||
zim = true;
|
||||
}
|
||||
for (int i = 0; i < (int)strlen(fn); i++) {
|
||||
if (fn[i] == '\\') fn[i] = '/';
|
||||
}
|
||||
|
||||
if (fn[0] == 'm') fn[0] = 'M';
|
||||
const char *name = fn;
|
||||
if (zim && 0==memcmp(name, "Media/textures/", strlen("Media/textures"))) name += strlen("Media/textures/");
|
||||
len = strlen(name);
|
||||
if (fn[0] == 'm') fn[0] = 'M';
|
||||
const char *name = fn;
|
||||
if (zim && 0==memcmp(name, "Media/textures/", strlen("Media/textures"))) name += strlen("Media/textures/");
|
||||
len = strlen(name);
|
||||
#ifndef ANDROID
|
||||
if (!strcmp("png", &name[len-3]) ||
|
||||
!strcmp("PNG", &name[len-3])) {
|
||||
if (!LoadPNG(fn)) {
|
||||
LoadXOR();
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else
|
||||
if (!strcmp("png", &name[len-3]) ||
|
||||
!strcmp("PNG", &name[len-3])) {
|
||||
if (!LoadPNG(fn)) {
|
||||
LoadXOR();
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
if (!strcmp("zim", &name[len-3])) {
|
||||
if (!LoadZIM(name)) {
|
||||
LoadXOR();
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
LoadXOR();
|
||||
return false;
|
||||
if (!strcmp("zim", &name[len-3])) {
|
||||
if (!LoadZIM(name)) {
|
||||
LoadXOR();
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
LoadXOR();
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifndef ANDROID
|
||||
bool Texture::LoadPNG(const char *filename) {
|
||||
unsigned char *image_data;
|
||||
if (1 != pngLoad(filename, &width_, &height_, &image_data, false)) {
|
||||
return false;
|
||||
}
|
||||
GL_CHECK();
|
||||
glGenTextures(1, &id_);
|
||||
glBindTexture(GL_TEXTURE_2D, id_);
|
||||
SetTextureParameters(ZIM_GEN_MIPS);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, image_data);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
GL_CHECK();
|
||||
free(image_data);
|
||||
return true;
|
||||
unsigned char *image_data;
|
||||
if (1 != pngLoad(filename, &width_, &height_, &image_data, false)) {
|
||||
return false;
|
||||
}
|
||||
GL_CHECK();
|
||||
glGenTextures(1, &id_);
|
||||
glBindTexture(GL_TEXTURE_2D, id_);
|
||||
SetTextureParameters(ZIM_GEN_MIPS);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, image_data);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
GL_CHECK();
|
||||
free(image_data);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool Texture::LoadXOR() {
|
||||
width_ = height_ = 256;
|
||||
unsigned char *buf = new unsigned char[width_*height_*4];
|
||||
for (int y = 0; y < 256; y++) {
|
||||
for (int x = 0; x < 256; x++) {
|
||||
buf[(y*width_ + x)*4 + 0] = x^y;
|
||||
buf[(y*width_ + x)*4 + 1] = x^y;
|
||||
buf[(y*width_ + x)*4 + 2] = x^y;
|
||||
buf[(y*width_ + x)*4 + 3] = 0xFF;
|
||||
}
|
||||
}
|
||||
GL_CHECK();
|
||||
glGenTextures(1, &id_);
|
||||
glBindTexture(GL_TEXTURE_2D, id_);
|
||||
SetTextureParameters(ZIM_GEN_MIPS);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, buf);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
GL_CHECK();
|
||||
delete [] buf;
|
||||
return true;
|
||||
width_ = height_ = 256;
|
||||
unsigned char *buf = new unsigned char[width_*height_*4];
|
||||
for (int y = 0; y < 256; y++) {
|
||||
for (int x = 0; x < 256; x++) {
|
||||
buf[(y*width_ + x)*4 + 0] = x^y;
|
||||
buf[(y*width_ + x)*4 + 1] = x^y;
|
||||
buf[(y*width_ + x)*4 + 2] = x^y;
|
||||
buf[(y*width_ + x)*4 + 3] = 0xFF;
|
||||
}
|
||||
}
|
||||
GL_CHECK();
|
||||
glGenTextures(1, &id_);
|
||||
glBindTexture(GL_TEXTURE_2D, id_);
|
||||
SetTextureParameters(ZIM_GEN_MIPS);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, buf);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
GL_CHECK();
|
||||
delete [] buf;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -188,97 +188,97 @@ bool Texture::LoadXOR() {
|
||||
|
||||
// Allocates using new[], doesn't free.
|
||||
uint8_t *ETC1ToRGBA(uint8_t *etc1, int width, int height) {
|
||||
uint8_t *rgba = new uint8_t[width * height * 4];
|
||||
memset(rgba, 0xFF, width * height * 4);
|
||||
for (int y = 0; y < height; y += 4) {
|
||||
for (int x = 0; x < width; x += 4) {
|
||||
DecompressBlock(etc1 + ((y / 4) * width/4 + (x / 4)) * 8,
|
||||
rgba + (y * width + x) * 4, width, 255);
|
||||
}
|
||||
}
|
||||
return rgba;
|
||||
uint8_t *rgba = new uint8_t[width * height * 4];
|
||||
memset(rgba, 0xFF, width * height * 4);
|
||||
for (int y = 0; y < height; y += 4) {
|
||||
for (int x = 0; x < width; x += 4) {
|
||||
DecompressBlock(etc1 + ((y / 4) * width/4 + (x / 4)) * 8,
|
||||
rgba + (y * width + x) * 4, width, 255);
|
||||
}
|
||||
}
|
||||
return rgba;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
bool Texture::LoadZIM(const char *filename) {
|
||||
uint8_t *image_data[ZIM_MAX_MIP_LEVELS];
|
||||
int width[ZIM_MAX_MIP_LEVELS];
|
||||
int height[ZIM_MAX_MIP_LEVELS];
|
||||
uint8_t *image_data[ZIM_MAX_MIP_LEVELS];
|
||||
int width[ZIM_MAX_MIP_LEVELS];
|
||||
int height[ZIM_MAX_MIP_LEVELS];
|
||||
|
||||
int flags;
|
||||
int num_levels = ::LoadZIM(filename, &width[0], &height[0], &flags, &image_data[0]);
|
||||
if (!num_levels)
|
||||
return false;
|
||||
width_ = width[0];
|
||||
height_ = height[0];
|
||||
int data_type = GL_UNSIGNED_BYTE;
|
||||
int colors = GL_RGBA;
|
||||
int storage = GL_RGBA;
|
||||
bool compressed = false;
|
||||
switch (flags & ZIM_FORMAT_MASK) {
|
||||
case ZIM_RGBA8888:
|
||||
data_type = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
case ZIM_RGBA4444:
|
||||
data_type = GL_UNSIGNED_SHORT_4_4_4_4;
|
||||
break;
|
||||
case ZIM_RGB565:
|
||||
data_type = GL_UNSIGNED_SHORT_5_6_5;
|
||||
colors = GL_RGB;
|
||||
storage = GL_RGB;
|
||||
break;
|
||||
case ZIM_ETC1:
|
||||
compressed = true;
|
||||
break;
|
||||
}
|
||||
int flags;
|
||||
int num_levels = ::LoadZIM(filename, &width[0], &height[0], &flags, &image_data[0]);
|
||||
if (!num_levels)
|
||||
return false;
|
||||
width_ = width[0];
|
||||
height_ = height[0];
|
||||
int data_type = GL_UNSIGNED_BYTE;
|
||||
int colors = GL_RGBA;
|
||||
int storage = GL_RGBA;
|
||||
bool compressed = false;
|
||||
switch (flags & ZIM_FORMAT_MASK) {
|
||||
case ZIM_RGBA8888:
|
||||
data_type = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
case ZIM_RGBA4444:
|
||||
data_type = GL_UNSIGNED_SHORT_4_4_4_4;
|
||||
break;
|
||||
case ZIM_RGB565:
|
||||
data_type = GL_UNSIGNED_SHORT_5_6_5;
|
||||
colors = GL_RGB;
|
||||
storage = GL_RGB;
|
||||
break;
|
||||
case ZIM_ETC1:
|
||||
compressed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
GL_CHECK();
|
||||
glGenTextures(1, &id_);
|
||||
glBindTexture(GL_TEXTURE_2D, id_);
|
||||
SetTextureParameters(flags);
|
||||
GL_CHECK();
|
||||
glGenTextures(1, &id_);
|
||||
glBindTexture(GL_TEXTURE_2D, id_);
|
||||
SetTextureParameters(flags);
|
||||
|
||||
if (compressed) {
|
||||
for (int l = 0; l < num_levels; l++) {
|
||||
int data_w = width[l];
|
||||
int data_h = height[l];
|
||||
if (data_w < 4) data_w = 4;
|
||||
if (data_h < 4) data_h = 4;
|
||||
if (compressed) {
|
||||
for (int l = 0; l < num_levels; l++) {
|
||||
int data_w = width[l];
|
||||
int data_h = height[l];
|
||||
if (data_w < 4) data_w = 4;
|
||||
if (data_h < 4) data_h = 4;
|
||||
#if defined(ANDROID)
|
||||
int compressed_image_bytes = data_w * data_h / 2;
|
||||
glCompressedTexImage2D(GL_TEXTURE_2D, l, GL_ETC1_RGB8_OES, width[l], height[l], 0, compressed_image_bytes, image_data[l]);
|
||||
GL_CHECK();
|
||||
int compressed_image_bytes = data_w * data_h / 2;
|
||||
glCompressedTexImage2D(GL_TEXTURE_2D, l, GL_ETC1_RGB8_OES, width[l], height[l], 0, compressed_image_bytes, image_data[l]);
|
||||
GL_CHECK();
|
||||
#else
|
||||
image_data[l] = ETC1ToRGBA(image_data[l], data_w, data_h);
|
||||
glTexImage2D(GL_TEXTURE_2D, l, GL_RGBA, width[l], height[l], 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, image_data[l]);
|
||||
image_data[l] = ETC1ToRGBA(image_data[l], data_w, data_h);
|
||||
glTexImage2D(GL_TEXTURE_2D, l, GL_RGBA, width[l], height[l], 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, image_data[l]);
|
||||
#endif
|
||||
}
|
||||
GL_CHECK();
|
||||
}
|
||||
GL_CHECK();
|
||||
#if !defined(ANDROID)
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, num_levels - 2);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, num_levels - 2);
|
||||
#endif
|
||||
} else {
|
||||
for (int l = 0; l < num_levels; l++) {
|
||||
glTexImage2D(GL_TEXTURE_2D, l, storage, width[l], height[l], 0,
|
||||
colors, data_type, image_data[l]);
|
||||
}
|
||||
if (num_levels == 1 && (flags & ZIM_GEN_MIPS)) {
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
}
|
||||
}
|
||||
SetTextureParameters(flags);
|
||||
} else {
|
||||
for (int l = 0; l < num_levels; l++) {
|
||||
glTexImage2D(GL_TEXTURE_2D, l, storage, width[l], height[l], 0,
|
||||
colors, data_type, image_data[l]);
|
||||
}
|
||||
if (num_levels == 1 && (flags & ZIM_GEN_MIPS)) {
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
}
|
||||
}
|
||||
SetTextureParameters(flags);
|
||||
|
||||
GL_CHECK();
|
||||
// Only free the top level, since the allocation is used for all of them.
|
||||
delete [] image_data[0];
|
||||
return true;
|
||||
GL_CHECK();
|
||||
// Only free the top level, since the allocation is used for all of them.
|
||||
delete [] image_data[0];
|
||||
return true;
|
||||
}
|
||||
|
||||
void Texture::Bind(int stage) {
|
||||
GL_CHECK();
|
||||
if (stage != -1)
|
||||
glActiveTexture(GL_TEXTURE0 + stage);
|
||||
glBindTexture(GL_TEXTURE_2D, id_);
|
||||
GL_CHECK();
|
||||
GL_CHECK();
|
||||
if (stage != -1)
|
||||
glActiveTexture(GL_TEXTURE0 + stage);
|
||||
glBindTexture(GL_TEXTURE_2D, id_);
|
||||
GL_CHECK();
|
||||
}
|
||||
|
||||
+20
-20
@@ -10,38 +10,38 @@
|
||||
|
||||
class Texture : public GfxResourceHolder {
|
||||
public:
|
||||
Texture();
|
||||
~Texture();
|
||||
Texture();
|
||||
~Texture();
|
||||
|
||||
bool LoadZIM(const char *filename);
|
||||
bool LoadZIM(const char *filename);
|
||||
#ifndef ANDROID
|
||||
bool LoadPNG(const char *filename);
|
||||
bool LoadPNG(const char *filename);
|
||||
#endif
|
||||
bool LoadXOR(); // Loads a placeholder texture.
|
||||
bool LoadXOR(); // Loads a placeholder texture.
|
||||
|
||||
// Deduces format from the filename.
|
||||
// If loading fails, will load a 256x256 XOR texture.
|
||||
// If filename begins with "gen:", will defer to texture_gen.cpp/h.
|
||||
bool Load(const char *filename);
|
||||
// Deduces format from the filename.
|
||||
// If loading fails, will load a 256x256 XOR texture.
|
||||
// If filename begins with "gen:", will defer to texture_gen.cpp/h.
|
||||
bool Load(const char *filename);
|
||||
|
||||
void Bind(int stage = -1);
|
||||
void Bind(int stage = -1);
|
||||
|
||||
void Destroy();
|
||||
void Destroy();
|
||||
|
||||
unsigned int Handle() const {
|
||||
return id_;
|
||||
}
|
||||
unsigned int Handle() const {
|
||||
return id_;
|
||||
}
|
||||
|
||||
virtual void GLLost();
|
||||
std::string filename() const { return filename_; }
|
||||
virtual void GLLost();
|
||||
std::string filename() const { return filename_; }
|
||||
|
||||
private:
|
||||
std::string filename_;
|
||||
std::string filename_;
|
||||
#ifdef METRO
|
||||
ID3D11Texture2D *tex_;
|
||||
ID3D11Texture2D *tex_;
|
||||
#endif
|
||||
unsigned int id_;
|
||||
int width_, height_;
|
||||
unsigned int id_;
|
||||
int width_, height_;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -7,7 +7,7 @@ const AtlasFont *Atlas::getFontByName(const char *name) const
|
||||
if (!strcmp(name, fonts[i]->name))
|
||||
return fonts[i];
|
||||
}
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const AtlasImage *Atlas::getImageByName(const char *name) const
|
||||
@@ -16,5 +16,5 @@ const AtlasImage *Atlas::getImageByName(const char *name) const
|
||||
if (!strcmp(name, images[i].name))
|
||||
return &images[i];
|
||||
}
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
+151
-151
@@ -23,7 +23,7 @@
|
||||
#include "gfx/gl_lost_manager.h"
|
||||
|
||||
Texture::Texture() : tex_(0) {
|
||||
register_gl_resource_holder(this);
|
||||
register_gl_resource_holder(this);
|
||||
|
||||
|
||||
|
||||
@@ -37,29 +37,29 @@ void Texture::Destroy() {
|
||||
}
|
||||
|
||||
void Texture::GLLost() {
|
||||
ILOG("Reloading lost texture %s", filename_.c_str());
|
||||
Load(filename_.c_str());
|
||||
ILOG("Reloading lost texture %s", filename_.c_str());
|
||||
Load(filename_.c_str());
|
||||
}
|
||||
|
||||
Texture::~Texture() {
|
||||
unregister_gl_resource_holder(this);
|
||||
Destroy();
|
||||
unregister_gl_resource_holder(this);
|
||||
Destroy();
|
||||
}
|
||||
|
||||
static void SetTextureParameters(int zim_flags) {
|
||||
/*
|
||||
GLenum wrap = GL_REPEAT;
|
||||
if (zim_flags & ZIM_CLAMP) wrap = GL_CLAMP_TO_EDGE;
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap);
|
||||
GL_CHECK();
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
if ((zim_flags & (ZIM_HAS_MIPS | ZIM_GEN_MIPS))) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
|
||||
} else {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
}
|
||||
GL_CHECK();*/
|
||||
GLenum wrap = GL_REPEAT;
|
||||
if (zim_flags & ZIM_CLAMP) wrap = GL_CLAMP_TO_EDGE;
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap);
|
||||
GL_CHECK();
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
if ((zim_flags & (ZIM_HAS_MIPS | ZIM_GEN_MIPS))) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
|
||||
} else {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
}
|
||||
GL_CHECK();*/
|
||||
}
|
||||
|
||||
bool Texture::Load(const char *filename) {
|
||||
@@ -74,70 +74,70 @@ bool Texture::Load(const char *filename) {
|
||||
return true;
|
||||
}
|
||||
|
||||
filename_ = filename;
|
||||
// Currently contains many Rollerball-specific workarounds.
|
||||
// They shouldn't really hurt anything else very much though.
|
||||
int len = strlen(filename);
|
||||
char fn[256];
|
||||
strcpy(fn, filename);
|
||||
bool zim = false;
|
||||
if (!strcmp("dds", &filename[len-3])) {
|
||||
strcpy(&fn[len-3], "zim");
|
||||
zim = true;
|
||||
}
|
||||
if (!strcmp("6TX", &filename[len-3]) || !strcmp("6tx", &filename[len-3])) {
|
||||
ILOG("Detected 6TX %s", filename);
|
||||
strcpy(&fn[len-3], "zim");
|
||||
zim = true;
|
||||
}
|
||||
for (int i = 0; i < (int)strlen(fn); i++) {
|
||||
if (fn[i] == '\\') fn[i] = '/';
|
||||
}
|
||||
filename_ = filename;
|
||||
// Currently contains many Rollerball-specific workarounds.
|
||||
// They shouldn't really hurt anything else very much though.
|
||||
int len = strlen(filename);
|
||||
char fn[256];
|
||||
strcpy(fn, filename);
|
||||
bool zim = false;
|
||||
if (!strcmp("dds", &filename[len-3])) {
|
||||
strcpy(&fn[len-3], "zim");
|
||||
zim = true;
|
||||
}
|
||||
if (!strcmp("6TX", &filename[len-3]) || !strcmp("6tx", &filename[len-3])) {
|
||||
ILOG("Detected 6TX %s", filename);
|
||||
strcpy(&fn[len-3], "zim");
|
||||
zim = true;
|
||||
}
|
||||
for (int i = 0; i < (int)strlen(fn); i++) {
|
||||
if (fn[i] == '\\') fn[i] = '/';
|
||||
}
|
||||
|
||||
if (fn[0] == 'm') fn[0] = 'M';
|
||||
const char *name = fn;
|
||||
if (zim && 0 == memcmp(name, "Media/textures/", strlen("Media/textures"))) name += strlen("Media/textures/");
|
||||
len = strlen(name);
|
||||
#ifndef ANDROID
|
||||
if (!strcmp("png", &name[len-3]) ||
|
||||
!strcmp("PNG", &name[len-3])) {
|
||||
if (!LoadPNG(fn)) {
|
||||
LoadXOR();
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
if (!strcmp("zim", &name[len-3])) {
|
||||
if (!LoadZIM(name)) {
|
||||
LoadXOR();
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
LoadXOR();
|
||||
return false;
|
||||
if (fn[0] == 'm') fn[0] = 'M';
|
||||
const char *name = fn;
|
||||
if (zim && 0 == memcmp(name, "Media/textures/", strlen("Media/textures"))) name += strlen("Media/textures/");
|
||||
len = strlen(name);
|
||||
#ifndef ANDROID
|
||||
if (!strcmp("png", &name[len-3]) ||
|
||||
!strcmp("PNG", &name[len-3])) {
|
||||
if (!LoadPNG(fn)) {
|
||||
LoadXOR();
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
if (!strcmp("zim", &name[len-3])) {
|
||||
if (!LoadZIM(name)) {
|
||||
LoadXOR();
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
LoadXOR();
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifndef METRO
|
||||
#ifndef ANDROID
|
||||
bool Texture::LoadPNG(const char *filename) {
|
||||
unsigned char *image_data;
|
||||
if (1 != pngLoad(filename, &width_, &height_, &image_data, false)) {
|
||||
return false;
|
||||
}
|
||||
GL_CHECK();
|
||||
glGenTextures(1, &id_);
|
||||
glBindTexture(GL_TEXTURE_2D, id_);
|
||||
SetTextureParameters(ZIM_GEN_MIPS);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, image_data);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
GL_CHECK();
|
||||
free(image_data);
|
||||
return true;
|
||||
unsigned char *image_data;
|
||||
if (1 != pngLoad(filename, &width_, &height_, &image_data, false)) {
|
||||
return false;
|
||||
}
|
||||
GL_CHECK();
|
||||
glGenTextures(1, &id_);
|
||||
glBindTexture(GL_TEXTURE_2D, id_);
|
||||
SetTextureParameters(ZIM_GEN_MIPS);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, image_data);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
GL_CHECK();
|
||||
free(image_data);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -153,7 +153,7 @@ bool Texture::LoadXOR() {
|
||||
buf[(y*width_ + x)*4 + 3] = 0xFF;
|
||||
}
|
||||
}
|
||||
GL_CHECK();
|
||||
GL_CHECK();
|
||||
ID3D11Device *ctx;
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
desc.Width = width_;
|
||||
@@ -169,10 +169,10 @@ bool Texture::LoadXOR() {
|
||||
if (FAILED(ctx->CreateTexture2D(&desc, 0, &tex_))) {
|
||||
FLOG("Failed creating XOR texture");
|
||||
}
|
||||
SetTextureParameters(ZIM_GEN_MIPS);
|
||||
GL_CHECK();
|
||||
delete [] buf;
|
||||
return true;
|
||||
SetTextureParameters(ZIM_GEN_MIPS);
|
||||
GL_CHECK();
|
||||
delete [] buf;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -180,97 +180,97 @@ bool Texture::LoadXOR() {
|
||||
|
||||
// Allocates using new[], doesn't free.
|
||||
uint8_t *ETC1ToRGBA(uint8_t *etc1, int width, int height) {
|
||||
uint8_t *rgba = new uint8_t[width * height * 4];
|
||||
memset(rgba, 0xFF, width * height * 4);
|
||||
for (int y = 0; y < height; y += 4) {
|
||||
for (int x = 0; x < width; x += 4) {
|
||||
DecompressBlock(etc1 + ((y / 4) * width/4 + (x / 4)) * 8,
|
||||
rgba + (y * width + x) * 4, width, 255);
|
||||
}
|
||||
}
|
||||
return rgba;
|
||||
uint8_t *rgba = new uint8_t[width * height * 4];
|
||||
memset(rgba, 0xFF, width * height * 4);
|
||||
for (int y = 0; y < height; y += 4) {
|
||||
for (int x = 0; x < width; x += 4) {
|
||||
DecompressBlock(etc1 + ((y / 4) * width/4 + (x / 4)) * 8,
|
||||
rgba + (y * width + x) * 4, width, 255);
|
||||
}
|
||||
}
|
||||
return rgba;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
bool Texture::LoadZIM(const char *filename) {
|
||||
uint8_t *image_data[ZIM_MAX_MIP_LEVELS];
|
||||
int width[ZIM_MAX_MIP_LEVELS];
|
||||
int height[ZIM_MAX_MIP_LEVELS];
|
||||
uint8_t *image_data[ZIM_MAX_MIP_LEVELS];
|
||||
int width[ZIM_MAX_MIP_LEVELS];
|
||||
int height[ZIM_MAX_MIP_LEVELS];
|
||||
|
||||
int flags;
|
||||
int num_levels = ::LoadZIM(filename, &width[0], &height[0], &flags, &image_data[0]);
|
||||
if (!num_levels)
|
||||
return false;
|
||||
width_ = width[0];
|
||||
height_ = height[0];
|
||||
int data_type = GL_UNSIGNED_BYTE;
|
||||
int colors = GL_RGBA;
|
||||
int storage = GL_RGBA;
|
||||
bool compressed = false;
|
||||
switch (flags & ZIM_FORMAT_MASK) {
|
||||
case ZIM_RGBA8888:
|
||||
data_type = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
case ZIM_RGBA4444:
|
||||
int flags;
|
||||
int num_levels = ::LoadZIM(filename, &width[0], &height[0], &flags, &image_data[0]);
|
||||
if (!num_levels)
|
||||
return false;
|
||||
width_ = width[0];
|
||||
height_ = height[0];
|
||||
int data_type = GL_UNSIGNED_BYTE;
|
||||
int colors = GL_RGBA;
|
||||
int storage = GL_RGBA;
|
||||
bool compressed = false;
|
||||
switch (flags & ZIM_FORMAT_MASK) {
|
||||
case ZIM_RGBA8888:
|
||||
data_type = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
case ZIM_RGBA4444:
|
||||
data_type = DXGI_FORMAT_B4G4R4A4_UNORM;
|
||||
break;
|
||||
case ZIM_RGB565:
|
||||
break;
|
||||
case ZIM_RGB565:
|
||||
data_type = DXGI_FORMAT_B5G6R5_UNORM;
|
||||
colors = GL_RGB;
|
||||
storage = GL_RGB;
|
||||
break;
|
||||
case ZIM_ETC1:
|
||||
compressed = true;
|
||||
break;
|
||||
}
|
||||
colors = GL_RGB;
|
||||
storage = GL_RGB;
|
||||
break;
|
||||
case ZIM_ETC1:
|
||||
compressed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
GL_CHECK();
|
||||
//glGenTextures(1, &id_);
|
||||
//glBindTexture(GL_TEXTURE_2D, id_);
|
||||
SetTextureParameters(flags);
|
||||
GL_CHECK();
|
||||
//glGenTextures(1, &id_);
|
||||
//glBindTexture(GL_TEXTURE_2D, id_);
|
||||
SetTextureParameters(flags);
|
||||
|
||||
if (compressed) {
|
||||
for (int l = 0; l < num_levels; l++) {
|
||||
int data_w = width[l];
|
||||
int data_h = height[l];
|
||||
if (data_w < 4) data_w = 4;
|
||||
if (data_h < 4) data_h = 4;
|
||||
if (compressed) {
|
||||
for (int l = 0; l < num_levels; l++) {
|
||||
int data_w = width[l];
|
||||
int data_h = height[l];
|
||||
if (data_w < 4) data_w = 4;
|
||||
if (data_h < 4) data_h = 4;
|
||||
#if defined(ANDROID)
|
||||
int compressed_image_bytes = data_w * data_h / 2;
|
||||
glCompressedTexImage2D(GL_TEXTURE_2D, l, GL_ETC1_RGB8_OES, width[l], height[l], 0, compressed_image_bytes, image_data[l]);
|
||||
GL_CHECK();
|
||||
int compressed_image_bytes = data_w * data_h / 2;
|
||||
glCompressedTexImage2D(GL_TEXTURE_2D, l, GL_ETC1_RGB8_OES, width[l], height[l], 0, compressed_image_bytes, image_data[l]);
|
||||
GL_CHECK();
|
||||
#else
|
||||
//image_data[l] = ETC1ToRGBA(image_data[l], data_w, data_h);
|
||||
//glTexImage2D(GL_TEXTURE_2D, l, GL_RGBA, width[l], height[l], 0,
|
||||
// GL_RGBA, GL_UNSIGNED_BYTE, image_data[l]);
|
||||
//image_data[l] = ETC1ToRGBA(image_data[l], data_w, data_h);
|
||||
//glTexImage2D(GL_TEXTURE_2D, l, GL_RGBA, width[l], height[l], 0,
|
||||
// GL_RGBA, GL_UNSIGNED_BYTE, image_data[l]);
|
||||
#endif
|
||||
}
|
||||
GL_CHECK();
|
||||
}
|
||||
GL_CHECK();
|
||||
#if !defined(ANDROID)
|
||||
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, num_levels - 2);
|
||||
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, num_levels - 2);
|
||||
#endif
|
||||
} else {
|
||||
for (int l = 0; l < num_levels; l++) {
|
||||
//glTexImage2D(GL_TEXTURE_2D, l, storage, width[l], height[l], 0,
|
||||
// colors, data_type, image_data[l]);
|
||||
}
|
||||
if (num_levels == 1 && (flags & ZIM_GEN_MIPS)) {
|
||||
//glGenerateMipmap(GL_TEXTURE_2D);
|
||||
}
|
||||
}
|
||||
SetTextureParameters(flags);
|
||||
} else {
|
||||
for (int l = 0; l < num_levels; l++) {
|
||||
//glTexImage2D(GL_TEXTURE_2D, l, storage, width[l], height[l], 0,
|
||||
// colors, data_type, image_data[l]);
|
||||
}
|
||||
if (num_levels == 1 && (flags & ZIM_GEN_MIPS)) {
|
||||
//glGenerateMipmap(GL_TEXTURE_2D);
|
||||
}
|
||||
}
|
||||
SetTextureParameters(flags);
|
||||
|
||||
GL_CHECK();
|
||||
// Only free the top level, since the allocation is used for all of them.
|
||||
delete [] image_data[0];
|
||||
return true;
|
||||
GL_CHECK();
|
||||
// Only free the top level, since the allocation is used for all of them.
|
||||
delete [] image_data[0];
|
||||
return true;
|
||||
}
|
||||
|
||||
void Texture::Bind(int stage) {
|
||||
GL_CHECK();
|
||||
GL_CHECK();
|
||||
//if (stage != -1)
|
||||
// glActiveTexture(GL_TEXTURE0 + stage);
|
||||
// glBindTexture(GL_TEXTURE_2D, id_);
|
||||
GL_CHECK();
|
||||
GL_CHECK();
|
||||
}
|
||||
|
||||
+35
-35
@@ -12,41 +12,41 @@
|
||||
|
||||
|
||||
uint8_t *generateTexture(const char *filename, int &bpp, int &w, int &h, bool &clamp) {
|
||||
char name_and_params[256];
|
||||
// security check :)
|
||||
if (strlen(filename) > 200)
|
||||
return 0;
|
||||
sscanf(filename, "gen:%i:%i:%s", &w, &h, name_and_params);
|
||||
char name_and_params[256];
|
||||
// security check :)
|
||||
if (strlen(filename) > 200)
|
||||
return 0;
|
||||
sscanf(filename, "gen:%i:%i:%s", &w, &h, name_and_params);
|
||||
|
||||
uint8_t *data;
|
||||
if (!strcmp(name_and_params, "vignette")) {
|
||||
bpp = 1;
|
||||
data = new uint8_t[w*h];
|
||||
for (int y = 0; y < h; ++y) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
float dx = (float)(x - w/2) / (w/2);
|
||||
float dy = (float)(y - h/2) / (h/2);
|
||||
float dist = sqrtf(dx * dx + dy * dy);
|
||||
dist /= 1.414f;
|
||||
float val = 1.0 - powf(dist, 1.4f);
|
||||
data[y*w + x] = val * 255;
|
||||
}
|
||||
}
|
||||
} else if (!strcmp(name_and_params, "circle")) {
|
||||
bpp = 1;
|
||||
// TODO
|
||||
data = new uint8_t[w*h];
|
||||
for (int y = 0; y < h; ++y) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
float dx = (float)(x - w/2) / (w/2);
|
||||
float dy = (float)(y - h/2) / (h/2);
|
||||
float dist = sqrtf(dx * dx + dy * dy);
|
||||
dist /= 1.414f;
|
||||
float val = 1.0 - powf(dist, 1.4f);
|
||||
data[y*w + x] = val * 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
uint8_t *data;
|
||||
if (!strcmp(name_and_params, "vignette")) {
|
||||
bpp = 1;
|
||||
data = new uint8_t[w*h];
|
||||
for (int y = 0; y < h; ++y) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
float dx = (float)(x - w/2) / (w/2);
|
||||
float dy = (float)(y - h/2) / (h/2);
|
||||
float dist = sqrtf(dx * dx + dy * dy);
|
||||
dist /= 1.414f;
|
||||
float val = 1.0 - powf(dist, 1.4f);
|
||||
data[y*w + x] = val * 255;
|
||||
}
|
||||
}
|
||||
} else if (!strcmp(name_and_params, "circle")) {
|
||||
bpp = 1;
|
||||
// TODO
|
||||
data = new uint8_t[w*h];
|
||||
for (int y = 0; y < h; ++y) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
float dx = (float)(x - w/2) / (w/2);
|
||||
float dy = (float)(y - h/2) / (h/2);
|
||||
float dist = sqrtf(dx * dx + dy * dy);
|
||||
dist /= 1.414f;
|
||||
float val = 1.0 - powf(dist, 1.4f);
|
||||
data[y*w + x] = val * 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
return data;
|
||||
}
|
||||
|
||||
+51
-51
@@ -14,77 +14,77 @@
|
||||
#include "gfx_es2/fbo.h"
|
||||
|
||||
struct FBO {
|
||||
GLuint handle;
|
||||
GLuint color_texture;
|
||||
GLuint z_stencil_buffer;
|
||||
GLuint handle;
|
||||
GLuint color_texture;
|
||||
GLuint z_stencil_buffer;
|
||||
|
||||
int width;
|
||||
int height;
|
||||
int width;
|
||||
int height;
|
||||
};
|
||||
|
||||
FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil) {
|
||||
FBO *fbo = new FBO();
|
||||
fbo->width = width;
|
||||
fbo->height = height;
|
||||
glGenFramebuffers(1, &fbo->handle);
|
||||
glGenTextures(1, &fbo->color_texture);
|
||||
glGenRenderbuffers(1, &fbo->z_stencil_buffer);
|
||||
FBO *fbo = new FBO();
|
||||
fbo->width = width;
|
||||
fbo->height = height;
|
||||
glGenFramebuffers(1, &fbo->handle);
|
||||
glGenTextures(1, &fbo->color_texture);
|
||||
glGenRenderbuffers(1, &fbo->z_stencil_buffer);
|
||||
|
||||
// Create the surfaces.
|
||||
glBindTexture(GL_TEXTURE_2D, fbo->color_texture);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
// Create the surfaces.
|
||||
glBindTexture(GL_TEXTURE_2D, fbo->color_texture);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, fbo->z_stencil_buffer);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, fbo->z_stencil_buffer);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height);
|
||||
|
||||
// Bind it all together
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo->handle);
|
||||
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0);
|
||||
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer);
|
||||
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
|
||||
switch(status) {
|
||||
case GL_FRAMEBUFFER_COMPLETE_EXT:
|
||||
ILOG("Framebuffer verified complete.");
|
||||
break;
|
||||
case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
|
||||
ELOG("Framebuffer format not supported");
|
||||
break;
|
||||
default:
|
||||
FLOG("Other framebuffer error: %i", status);
|
||||
break;
|
||||
}
|
||||
// Unbind state we don't need
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
return fbo;
|
||||
// Bind it all together
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo->handle);
|
||||
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0);
|
||||
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer);
|
||||
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
|
||||
switch(status) {
|
||||
case GL_FRAMEBUFFER_COMPLETE_EXT:
|
||||
ILOG("Framebuffer verified complete.");
|
||||
break;
|
||||
case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
|
||||
ELOG("Framebuffer format not supported");
|
||||
break;
|
||||
default:
|
||||
FLOG("Other framebuffer error: %i", status);
|
||||
break;
|
||||
}
|
||||
// Unbind state we don't need
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
return fbo;
|
||||
}
|
||||
|
||||
void fbo_unbind() {
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
void fbo_bind_as_render_target(FBO *fbo) {
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo->handle);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo->handle);
|
||||
}
|
||||
|
||||
void fbo_bind_for_read(FBO *fbo) {
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo->handle);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo->handle);
|
||||
}
|
||||
|
||||
void fbo_bind_color_as_texture(FBO *fbo, int color) {
|
||||
glBindTexture(GL_TEXTURE_2D, fbo->color_texture);
|
||||
glBindTexture(GL_TEXTURE_2D, fbo->color_texture);
|
||||
}
|
||||
|
||||
void fbo_destroy(FBO *fbo) {
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo->handle);
|
||||
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
|
||||
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
glDeleteFramebuffers(1, &fbo->handle);
|
||||
glDeleteTextures(1, &fbo->color_texture);
|
||||
glDeleteRenderbuffers(1, &fbo->z_stencil_buffer);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo->handle);
|
||||
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
|
||||
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
glDeleteFramebuffers(1, &fbo->handle);
|
||||
glDeleteTextures(1, &fbo->color_texture);
|
||||
glDeleteRenderbuffers(1, &fbo->z_stencil_buffer);
|
||||
}
|
||||
|
||||
+166
-166
@@ -24,189 +24,189 @@ typedef char GLchar;
|
||||
static std::set<GLSLProgram *> active_programs;
|
||||
|
||||
bool CompileShader(const char *source, GLuint shader, const char *filename) {
|
||||
glShaderSource(shader, 1, &source, NULL);
|
||||
glCompileShader(shader);
|
||||
GLint success;
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
|
||||
if (!success) {
|
||||
glShaderSource(shader, 1, &source, NULL);
|
||||
glCompileShader(shader);
|
||||
GLint success;
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
|
||||
if (!success) {
|
||||
#define MAX_INFO_LOG_SIZE 2048
|
||||
GLchar infoLog[MAX_INFO_LOG_SIZE];
|
||||
GLsizei len;
|
||||
glGetShaderInfoLog(shader, MAX_INFO_LOG_SIZE, &len, infoLog);
|
||||
infoLog[len] = '\0';
|
||||
ELOG("Error in shader compilation of %s!\n", filename);
|
||||
ELOG("Info log: %s\n", infoLog);
|
||||
ELOG("Shader source:\n%s\n", (const char *)source);
|
||||
GLchar infoLog[MAX_INFO_LOG_SIZE];
|
||||
GLsizei len;
|
||||
glGetShaderInfoLog(shader, MAX_INFO_LOG_SIZE, &len, infoLog);
|
||||
infoLog[len] = '\0';
|
||||
ELOG("Error in shader compilation of %s!\n", filename);
|
||||
ELOG("Info log: %s\n", infoLog);
|
||||
ELOG("Shader source:\n%s\n", (const char *)source);
|
||||
#ifdef ANDROID
|
||||
exit(1);
|
||||
exit(1);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
GLSLProgram *glsl_create(const char *vshader, const char *fshader) {
|
||||
GLSLProgram *program = new GLSLProgram();
|
||||
program->program_ = 0;
|
||||
program->vsh_ = 0;
|
||||
program->fsh_ = 0;
|
||||
program->vshader_source = 0;
|
||||
program->fshader_source = 0;
|
||||
strcpy(program->name, vshader + strlen(vshader) - 15);
|
||||
strcpy(program->vshader_filename, vshader);
|
||||
strcpy(program->fshader_filename, fshader);
|
||||
if (glsl_recompile(program)) {
|
||||
active_programs.insert(program);
|
||||
}
|
||||
else
|
||||
{
|
||||
FLOG("Failed building GLSL program: %s %s", vshader, fshader);
|
||||
}
|
||||
register_gl_resource_holder(program);
|
||||
return program;
|
||||
GLSLProgram *program = new GLSLProgram();
|
||||
program->program_ = 0;
|
||||
program->vsh_ = 0;
|
||||
program->fsh_ = 0;
|
||||
program->vshader_source = 0;
|
||||
program->fshader_source = 0;
|
||||
strcpy(program->name, vshader + strlen(vshader) - 15);
|
||||
strcpy(program->vshader_filename, vshader);
|
||||
strcpy(program->fshader_filename, fshader);
|
||||
if (glsl_recompile(program)) {
|
||||
active_programs.insert(program);
|
||||
}
|
||||
else
|
||||
{
|
||||
FLOG("Failed building GLSL program: %s %s", vshader, fshader);
|
||||
}
|
||||
register_gl_resource_holder(program);
|
||||
return program;
|
||||
}
|
||||
|
||||
GLSLProgram *glsl_create_source(const char *vshader_src, const char *fshader_src) {
|
||||
GLSLProgram *program = new GLSLProgram();
|
||||
program->program_ = 0;
|
||||
program->vsh_ = 0;
|
||||
program->fsh_ = 0;
|
||||
program->vshader_source = vshader_src;
|
||||
program->fshader_source = fshader_src;
|
||||
strcpy(program->name, "[srcshader]");
|
||||
strcpy(program->vshader_filename, "");
|
||||
strcpy(program->fshader_filename, "");
|
||||
if (glsl_recompile(program)) {
|
||||
active_programs.insert(program);
|
||||
}
|
||||
register_gl_resource_holder(program);
|
||||
return program;
|
||||
GLSLProgram *program = new GLSLProgram();
|
||||
program->program_ = 0;
|
||||
program->vsh_ = 0;
|
||||
program->fsh_ = 0;
|
||||
program->vshader_source = vshader_src;
|
||||
program->fshader_source = fshader_src;
|
||||
strcpy(program->name, "[srcshader]");
|
||||
strcpy(program->vshader_filename, "");
|
||||
strcpy(program->fshader_filename, "");
|
||||
if (glsl_recompile(program)) {
|
||||
active_programs.insert(program);
|
||||
}
|
||||
register_gl_resource_holder(program);
|
||||
return program;
|
||||
}
|
||||
|
||||
bool glsl_up_to_date(GLSLProgram *program) {
|
||||
struct stat vs, fs;
|
||||
stat(program->vshader_filename, &vs);
|
||||
stat(program->fshader_filename, &fs);
|
||||
if (vs.st_mtime != program->vshader_mtime ||
|
||||
fs.st_mtime != program->fshader_mtime) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
struct stat vs, fs;
|
||||
stat(program->vshader_filename, &vs);
|
||||
stat(program->fshader_filename, &fs);
|
||||
if (vs.st_mtime != program->vshader_mtime ||
|
||||
fs.st_mtime != program->fshader_mtime) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void glsl_refresh() {
|
||||
ILOG("glsl_refresh()");
|
||||
for (std::set<GLSLProgram *>::const_iterator iter = active_programs.begin();
|
||||
iter != active_programs.end(); ++iter) {
|
||||
if (!glsl_up_to_date(*iter)) {
|
||||
glsl_recompile(*iter);
|
||||
}
|
||||
}
|
||||
ILOG("glsl_refresh()");
|
||||
for (std::set<GLSLProgram *>::const_iterator iter = active_programs.begin();
|
||||
iter != active_programs.end(); ++iter) {
|
||||
if (!glsl_up_to_date(*iter)) {
|
||||
glsl_recompile(*iter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool glsl_recompile(GLSLProgram *program) {
|
||||
struct stat vs, fs;
|
||||
if (0 == stat(program->vshader_filename, &vs))
|
||||
program->vshader_mtime = vs.st_mtime;
|
||||
else
|
||||
program->vshader_mtime = 0;
|
||||
struct stat vs, fs;
|
||||
if (0 == stat(program->vshader_filename, &vs))
|
||||
program->vshader_mtime = vs.st_mtime;
|
||||
else
|
||||
program->vshader_mtime = 0;
|
||||
|
||||
if (0 == stat(program->fshader_filename, &fs))
|
||||
program->fshader_mtime = fs.st_mtime;
|
||||
else
|
||||
program->fshader_mtime = 0;
|
||||
|
||||
char *vsh_src = 0, *fsh_src = 0;
|
||||
if (0 == stat(program->fshader_filename, &fs))
|
||||
program->fshader_mtime = fs.st_mtime;
|
||||
else
|
||||
program->fshader_mtime = 0;
|
||||
|
||||
char *vsh_src = 0, *fsh_src = 0;
|
||||
|
||||
if (!program->vshader_source)
|
||||
{
|
||||
size_t sz;
|
||||
vsh_src = (char *)VFSReadFile(program->vshader_filename, &sz);
|
||||
if (!vsh_src) {
|
||||
ELOG("File missing: %s", program->vshader_filename);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!program->fshader_source)
|
||||
{
|
||||
size_t sz;
|
||||
fsh_src = (char *)VFSReadFile(program->fshader_filename, &sz);
|
||||
if (!fsh_src) {
|
||||
ELOG("File missing: %s", program->fshader_filename);
|
||||
delete [] vsh_src;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!program->vshader_source)
|
||||
{
|
||||
size_t sz;
|
||||
vsh_src = (char *)VFSReadFile(program->vshader_filename, &sz);
|
||||
if (!vsh_src) {
|
||||
ELOG("File missing: %s", program->vshader_filename);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!program->fshader_source)
|
||||
{
|
||||
size_t sz;
|
||||
fsh_src = (char *)VFSReadFile(program->fshader_filename, &sz);
|
||||
if (!fsh_src) {
|
||||
ELOG("File missing: %s", program->fshader_filename);
|
||||
delete [] vsh_src;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
GLuint vsh = glCreateShader(GL_VERTEX_SHADER);
|
||||
const GLchar *vsh_str = program->vshader_source ? program->vshader_source : (const GLchar *)(vsh_src);
|
||||
if (!CompileShader(vsh_str, vsh, program->vshader_filename)) {
|
||||
return false;
|
||||
}
|
||||
delete [] vsh_src;
|
||||
GLuint vsh = glCreateShader(GL_VERTEX_SHADER);
|
||||
const GLchar *vsh_str = program->vshader_source ? program->vshader_source : (const GLchar *)(vsh_src);
|
||||
if (!CompileShader(vsh_str, vsh, program->vshader_filename)) {
|
||||
return false;
|
||||
}
|
||||
delete [] vsh_src;
|
||||
|
||||
const GLchar *fsh_str = program->fshader_source ? program->fshader_source : (const GLchar *)(fsh_src);
|
||||
GLuint fsh = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
if (!CompileShader(fsh_str, fsh, program->fshader_filename)) {
|
||||
glDeleteShader(vsh);
|
||||
return false;
|
||||
}
|
||||
delete [] fsh_src;
|
||||
const GLchar *fsh_str = program->fshader_source ? program->fshader_source : (const GLchar *)(fsh_src);
|
||||
GLuint fsh = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
if (!CompileShader(fsh_str, fsh, program->fshader_filename)) {
|
||||
glDeleteShader(vsh);
|
||||
return false;
|
||||
}
|
||||
delete [] fsh_src;
|
||||
|
||||
GLuint prog = glCreateProgram();
|
||||
glAttachShader(prog, vsh);
|
||||
glAttachShader(prog, fsh);
|
||||
GLuint prog = glCreateProgram();
|
||||
glAttachShader(prog, vsh);
|
||||
glAttachShader(prog, fsh);
|
||||
|
||||
glLinkProgram(prog);
|
||||
glLinkProgram(prog);
|
||||
|
||||
GLint linkStatus;
|
||||
glGetProgramiv(prog, GL_LINK_STATUS, &linkStatus);
|
||||
if (linkStatus != GL_TRUE) {
|
||||
GLint bufLength = 0;
|
||||
glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &bufLength);
|
||||
if (bufLength) {
|
||||
char* buf = new char[bufLength];
|
||||
glGetProgramInfoLog(prog, bufLength, NULL, buf);
|
||||
FLOG("Could not link program:\n %s", buf);
|
||||
delete [] buf; // we're dead!
|
||||
} else {
|
||||
FLOG("Could not link program.");
|
||||
}
|
||||
glDeleteShader(vsh);
|
||||
glDeleteShader(fsh);
|
||||
return false;
|
||||
}
|
||||
GLint linkStatus;
|
||||
glGetProgramiv(prog, GL_LINK_STATUS, &linkStatus);
|
||||
if (linkStatus != GL_TRUE) {
|
||||
GLint bufLength = 0;
|
||||
glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &bufLength);
|
||||
if (bufLength) {
|
||||
char* buf = new char[bufLength];
|
||||
glGetProgramInfoLog(prog, bufLength, NULL, buf);
|
||||
FLOG("Could not link program:\n %s", buf);
|
||||
delete [] buf; // we're dead!
|
||||
} else {
|
||||
FLOG("Could not link program.");
|
||||
}
|
||||
glDeleteShader(vsh);
|
||||
glDeleteShader(fsh);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Destroy the old program, if any.
|
||||
if (program->program_) {
|
||||
glDeleteProgram(program->program_);
|
||||
}
|
||||
// Destroy the old program, if any.
|
||||
if (program->program_) {
|
||||
glDeleteProgram(program->program_);
|
||||
}
|
||||
|
||||
program->program_ = prog;
|
||||
program->vsh_ = vsh;
|
||||
program->fsh_ = vsh;
|
||||
program->program_ = prog;
|
||||
program->vsh_ = vsh;
|
||||
program->fsh_ = vsh;
|
||||
|
||||
program->sampler0 = glGetUniformLocation(program->program_, "sampler0");
|
||||
program->sampler1 = glGetUniformLocation(program->program_, "sampler1");
|
||||
program->sampler0 = glGetUniformLocation(program->program_, "sampler0");
|
||||
program->sampler1 = glGetUniformLocation(program->program_, "sampler1");
|
||||
|
||||
program->a_position = glGetAttribLocation(program->program_, "a_position");
|
||||
program->a_color = glGetAttribLocation(program->program_, "a_color");
|
||||
program->a_normal = glGetAttribLocation(program->program_, "a_normal");
|
||||
program->a_texcoord0 = glGetAttribLocation(program->program_, "a_texcoord0");
|
||||
program->a_texcoord1 = glGetAttribLocation(program->program_, "a_texcoord1");
|
||||
program->a_position = glGetAttribLocation(program->program_, "a_position");
|
||||
program->a_color = glGetAttribLocation(program->program_, "a_color");
|
||||
program->a_normal = glGetAttribLocation(program->program_, "a_normal");
|
||||
program->a_texcoord0 = glGetAttribLocation(program->program_, "a_texcoord0");
|
||||
program->a_texcoord1 = glGetAttribLocation(program->program_, "a_texcoord1");
|
||||
|
||||
program->u_worldviewproj = glGetUniformLocation(program->program_, "u_worldviewproj");
|
||||
program->u_world = glGetUniformLocation(program->program_, "u_world");
|
||||
program->u_viewproj = glGetUniformLocation(program->program_, "u_viewproj");
|
||||
program->u_fog = glGetUniformLocation(program->program_, "u_fog");
|
||||
program->u_sundir = glGetUniformLocation(program->program_, "u_sundir");
|
||||
program->u_camerapos = glGetUniformLocation(program->program_, "u_camerapos");
|
||||
program->u_worldviewproj = glGetUniformLocation(program->program_, "u_worldviewproj");
|
||||
program->u_world = glGetUniformLocation(program->program_, "u_world");
|
||||
program->u_viewproj = glGetUniformLocation(program->program_, "u_viewproj");
|
||||
program->u_fog = glGetUniformLocation(program->program_, "u_fog");
|
||||
program->u_sundir = glGetUniformLocation(program->program_, "u_sundir");
|
||||
program->u_camerapos = glGetUniformLocation(program->program_, "u_camerapos");
|
||||
|
||||
//ILOG("Shader compilation success: %s %s",
|
||||
// program->vshader_filename,
|
||||
// program->fshader_filename);
|
||||
return true;
|
||||
//ILOG("Shader compilation success: %s %s",
|
||||
// program->vshader_filename,
|
||||
// program->fshader_filename);
|
||||
return true;
|
||||
}
|
||||
|
||||
void GLSLProgram::GLLost() {
|
||||
@@ -220,35 +220,35 @@ void GLSLProgram::GLLost() {
|
||||
ILOG("Restoring GLSL program %s/%s",
|
||||
this->vshader_filename ? this->vshader_filename : "(mem)",
|
||||
this->fshader_filename ? this->fshader_filename : "(mem)");
|
||||
this->program_ = 0;
|
||||
this->vsh_ = 0;
|
||||
this->fsh_ = 0;
|
||||
glsl_recompile(this);
|
||||
this->program_ = 0;
|
||||
this->vsh_ = 0;
|
||||
this->fsh_ = 0;
|
||||
glsl_recompile(this);
|
||||
// Note that uniforms are still lost, hopefully the client sets them every frame at a minimum...
|
||||
}
|
||||
|
||||
|
||||
int glsl_attrib_loc(const GLSLProgram *program, const char *name) {
|
||||
return glGetAttribLocation(program->program_, name);
|
||||
return glGetAttribLocation(program->program_, name);
|
||||
}
|
||||
|
||||
int glsl_uniform_loc(const GLSLProgram *program, const char *name) {
|
||||
return glGetUniformLocation(program->program_, name);
|
||||
return glGetUniformLocation(program->program_, name);
|
||||
}
|
||||
|
||||
void glsl_destroy(GLSLProgram *program) {
|
||||
unregister_gl_resource_holder(program);
|
||||
glDeleteShader(program->vsh_);
|
||||
glDeleteShader(program->fsh_);
|
||||
glDeleteProgram(program->program_);
|
||||
active_programs.erase(program);
|
||||
delete program;
|
||||
unregister_gl_resource_holder(program);
|
||||
glDeleteShader(program->vsh_);
|
||||
glDeleteShader(program->fsh_);
|
||||
glDeleteProgram(program->program_);
|
||||
active_programs.erase(program);
|
||||
delete program;
|
||||
}
|
||||
|
||||
void glsl_bind(const GLSLProgram *program) {
|
||||
glUseProgram(program->program_);
|
||||
glUseProgram(program->program_);
|
||||
}
|
||||
|
||||
void glsl_unbind() {
|
||||
glUseProgram(0);
|
||||
glUseProgram(0);
|
||||
}
|
||||
|
||||
+25
-25
@@ -25,36 +25,36 @@
|
||||
// A just-constructed object is valid but cannot be used as a shader program, meaning that
|
||||
// yes, you can declare these as globals if you like.
|
||||
struct GLSLProgram : public GfxResourceHolder {
|
||||
char name[16];
|
||||
char vshader_filename[256];
|
||||
char fshader_filename[256];
|
||||
const char *vshader_source;
|
||||
const char *fshader_source;
|
||||
time_t vshader_mtime;
|
||||
time_t fshader_mtime;
|
||||
char name[16];
|
||||
char vshader_filename[256];
|
||||
char fshader_filename[256];
|
||||
const char *vshader_source;
|
||||
const char *fshader_source;
|
||||
time_t vshader_mtime;
|
||||
time_t fshader_mtime;
|
||||
|
||||
// Locations to some common uniforms. Hardcoded for speed.
|
||||
GLint sampler0;
|
||||
GLint sampler1;
|
||||
GLint u_worldviewproj;
|
||||
GLint u_world;
|
||||
GLint u_viewproj;
|
||||
GLint u_fog; // rgb = color, a = density
|
||||
// Locations to some common uniforms. Hardcoded for speed.
|
||||
GLint sampler0;
|
||||
GLint sampler1;
|
||||
GLint u_worldviewproj;
|
||||
GLint u_world;
|
||||
GLint u_viewproj;
|
||||
GLint u_fog; // rgb = color, a = density
|
||||
GLint u_sundir;
|
||||
GLint u_camerapos;
|
||||
|
||||
GLint a_position;
|
||||
GLint a_color;
|
||||
GLint a_normal;
|
||||
GLint a_texcoord0;
|
||||
GLint a_texcoord1;
|
||||
GLint a_position;
|
||||
GLint a_color;
|
||||
GLint a_normal;
|
||||
GLint a_texcoord0;
|
||||
GLint a_texcoord1;
|
||||
|
||||
// Private to the implementation, do not touch
|
||||
GLuint vsh_;
|
||||
GLuint fsh_;
|
||||
GLuint program_;
|
||||
// Private to the implementation, do not touch
|
||||
GLuint vsh_;
|
||||
GLuint fsh_;
|
||||
GLuint program_;
|
||||
|
||||
void GLLost();
|
||||
void GLLost();
|
||||
};
|
||||
|
||||
|
||||
@@ -81,4 +81,4 @@ void glsl_refresh();
|
||||
|
||||
// Use glUseProgramObjectARB(NULL); to unset.
|
||||
|
||||
#endif // _RENDER_UTIL
|
||||
#endif // _RENDER_UTIL
|
||||
|
||||
+52
-52
@@ -3,69 +3,69 @@
|
||||
#include "gfx_es2/vertex_format.h"
|
||||
|
||||
static const GLuint formatLookup[16] = {
|
||||
GL_FLOAT,
|
||||
0, //GL_HALF_FLOAT_EXT,
|
||||
GL_UNSIGNED_SHORT,
|
||||
GL_UNSIGNED_BYTE,
|
||||
0, //GL_UNSIGNED_INT_10_10_10_2,
|
||||
0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0
|
||||
GL_FLOAT,
|
||||
0, //GL_HALF_FLOAT_EXT,
|
||||
GL_UNSIGNED_SHORT,
|
||||
GL_UNSIGNED_BYTE,
|
||||
0, //GL_UNSIGNED_INT_10_10_10_2,
|
||||
0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
void SetVertexFormat(const GLSLProgram *program, uint32_t vertexFormat) {
|
||||
// First special case our favorites
|
||||
if (vertexFormat == (POS_FLOAT | NRM_FLOAT | UV0_FLOAT)) {
|
||||
const int vertexSize = 3*4 + 3*4 + 2*4;
|
||||
glUniform1i(program->sampler0, 0);
|
||||
glEnableVertexAttribArray(program->a_position);
|
||||
glEnableVertexAttribArray(program->a_normal);
|
||||
glEnableVertexAttribArray(program->a_texcoord0);
|
||||
glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, vertexSize, (void *)0);
|
||||
glVertexAttribPointer(program->a_normal, 3, GL_FLOAT, GL_FALSE, vertexSize, (void *)12);
|
||||
glVertexAttribPointer(program->a_texcoord0, 2, GL_FLOAT, GL_FALSE, vertexSize, (void *)24);
|
||||
return;
|
||||
}
|
||||
// First special case our favorites
|
||||
if (vertexFormat == (POS_FLOAT | NRM_FLOAT | UV0_FLOAT)) {
|
||||
const int vertexSize = 3*4 + 3*4 + 2*4;
|
||||
glUniform1i(program->sampler0, 0);
|
||||
glEnableVertexAttribArray(program->a_position);
|
||||
glEnableVertexAttribArray(program->a_normal);
|
||||
glEnableVertexAttribArray(program->a_texcoord0);
|
||||
glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, vertexSize, (void *)0);
|
||||
glVertexAttribPointer(program->a_normal, 3, GL_FLOAT, GL_FALSE, vertexSize, (void *)12);
|
||||
glVertexAttribPointer(program->a_texcoord0, 2, GL_FLOAT, GL_FALSE, vertexSize, (void *)24);
|
||||
return;
|
||||
}
|
||||
|
||||
// Then have generic code here.
|
||||
// Then have generic code here.
|
||||
|
||||
|
||||
int vertexSize = 0;
|
||||
int vertexSize = 0;
|
||||
|
||||
FLOG("TODO: Write generic code.");
|
||||
FLOG("TODO: Write generic code.");
|
||||
|
||||
if (vertexFormat & UV0_MASK) {
|
||||
glUniform1i(program->sampler0, 0);
|
||||
}
|
||||
if (vertexFormat & UV0_MASK) {
|
||||
glUniform1i(program->sampler0, 0);
|
||||
}
|
||||
|
||||
glEnableVertexAttribArray(program->a_position);
|
||||
glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, vertexSize, (void *)0);
|
||||
if (vertexFormat & NRM_MASK) {
|
||||
glEnableVertexAttribArray(program->a_normal);
|
||||
glVertexAttribPointer(program->a_normal, 3, GL_FLOAT, GL_FALSE, vertexSize, (void *)12);
|
||||
}
|
||||
if (vertexFormat & UV0_MASK) {
|
||||
glEnableVertexAttribArray(program->a_texcoord0);
|
||||
glVertexAttribPointer(program->a_texcoord0, 2, GL_FLOAT, GL_FALSE, vertexSize, (void *)24);
|
||||
}
|
||||
if (vertexFormat & UV1_MASK) {
|
||||
glEnableVertexAttribArray(program->a_texcoord1);
|
||||
glVertexAttribPointer(program->a_texcoord1, 2, GL_FLOAT, GL_FALSE, vertexSize, (void *)24);
|
||||
}
|
||||
if (vertexFormat & RGBA_MASK) {
|
||||
glEnableVertexAttribArray(program->a_color);
|
||||
glVertexAttribPointer(program->a_color, 4, GL_FLOAT, GL_FALSE, vertexSize, (void *)28);
|
||||
}
|
||||
glEnableVertexAttribArray(program->a_position);
|
||||
glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, vertexSize, (void *)0);
|
||||
if (vertexFormat & NRM_MASK) {
|
||||
glEnableVertexAttribArray(program->a_normal);
|
||||
glVertexAttribPointer(program->a_normal, 3, GL_FLOAT, GL_FALSE, vertexSize, (void *)12);
|
||||
}
|
||||
if (vertexFormat & UV0_MASK) {
|
||||
glEnableVertexAttribArray(program->a_texcoord0);
|
||||
glVertexAttribPointer(program->a_texcoord0, 2, GL_FLOAT, GL_FALSE, vertexSize, (void *)24);
|
||||
}
|
||||
if (vertexFormat & UV1_MASK) {
|
||||
glEnableVertexAttribArray(program->a_texcoord1);
|
||||
glVertexAttribPointer(program->a_texcoord1, 2, GL_FLOAT, GL_FALSE, vertexSize, (void *)24);
|
||||
}
|
||||
if (vertexFormat & RGBA_MASK) {
|
||||
glEnableVertexAttribArray(program->a_color);
|
||||
glVertexAttribPointer(program->a_color, 4, GL_FLOAT, GL_FALSE, vertexSize, (void *)28);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Save state so that we can get rid of this.
|
||||
void UnsetVertexFormat(const GLSLProgram *program, uint32 vertexFormat) {
|
||||
glDisableVertexAttribArray(program->a_position);
|
||||
if (vertexFormat & NRM_MASK)
|
||||
glDisableVertexAttribArray(program->a_normal);
|
||||
if (vertexFormat & UV0_MASK)
|
||||
glDisableVertexAttribArray(program->a_texcoord0);
|
||||
if (vertexFormat & UV1_MASK)
|
||||
glDisableVertexAttribArray(program->a_texcoord1);
|
||||
if (vertexFormat & RGBA_MASK)
|
||||
glDisableVertexAttribArray(program->a_color);
|
||||
glDisableVertexAttribArray(program->a_position);
|
||||
if (vertexFormat & NRM_MASK)
|
||||
glDisableVertexAttribArray(program->a_normal);
|
||||
if (vertexFormat & UV0_MASK)
|
||||
glDisableVertexAttribArray(program->a_texcoord0);
|
||||
if (vertexFormat & UV1_MASK)
|
||||
glDisableVertexAttribArray(program->a_texcoord1);
|
||||
if (vertexFormat & RGBA_MASK)
|
||||
glDisableVertexAttribArray(program->a_color);
|
||||
}
|
||||
|
||||
+30
-30
@@ -6,42 +6,42 @@
|
||||
|
||||
// Vertex format flags
|
||||
enum VtxFmt {
|
||||
POS_FLOAT = 1,
|
||||
POS_FLOAT16 = 2,
|
||||
POS_UINT16 = 3,
|
||||
POS_UINT8 = 4,
|
||||
POS_101010 = 5,
|
||||
POS_FLOAT = 1,
|
||||
POS_FLOAT16 = 2,
|
||||
POS_UINT16 = 3,
|
||||
POS_UINT8 = 4,
|
||||
POS_101010 = 5,
|
||||
|
||||
NRM_FLOAT = 1 << 4,
|
||||
NRM_FLOAT16 = 2 << 4,
|
||||
NRM_SINT16 = 3 << 4,
|
||||
NRM_UINT8 = 4 << 4,
|
||||
NRM_101010 = 5 << 4,
|
||||
NRM_FLOAT = 1 << 4,
|
||||
NRM_FLOAT16 = 2 << 4,
|
||||
NRM_SINT16 = 3 << 4,
|
||||
NRM_UINT8 = 4 << 4,
|
||||
NRM_101010 = 5 << 4,
|
||||
|
||||
TANGENT_FLOAT = 1 << 8,
|
||||
//....
|
||||
TANGENT_FLOAT = 1 << 8,
|
||||
//....
|
||||
|
||||
UV0_NONE = 1 << 12,
|
||||
UV0_FLOAT = 1 << 12,
|
||||
// ....
|
||||
UV1_NONE = 1 << 16,
|
||||
UV1_FLOAT = 1 << 16,
|
||||
UV0_NONE = 1 << 12,
|
||||
UV0_FLOAT = 1 << 12,
|
||||
// ....
|
||||
UV1_NONE = 1 << 16,
|
||||
UV1_FLOAT = 1 << 16,
|
||||
|
||||
RGBA_NONE = 0 << 20,
|
||||
RGBA_FLOAT = 1 << 20,
|
||||
RGBA_FLOAT16 = 2 << 20,
|
||||
RGBA_UINT16 = 3 << 20,
|
||||
RGBA_UINT8 = 4 << 20,
|
||||
RGBA_101010 = 5 << 20,
|
||||
RGBA_NONE = 0 << 20,
|
||||
RGBA_FLOAT = 1 << 20,
|
||||
RGBA_FLOAT16 = 2 << 20,
|
||||
RGBA_UINT16 = 3 << 20,
|
||||
RGBA_UINT8 = 4 << 20,
|
||||
RGBA_101010 = 5 << 20,
|
||||
|
||||
POS_MASK = 0x0000000F,
|
||||
NRM_MASK = 0x000000F0,
|
||||
TANGENT_MASK = 0x00000F00,
|
||||
UV0_MASK = 0x0000F000,
|
||||
UV1_MASK = 0x000F0000,
|
||||
RGBA_MASK = 0x00F00000,
|
||||
POS_MASK = 0x0000000F,
|
||||
NRM_MASK = 0x000000F0,
|
||||
TANGENT_MASK = 0x00000F00,
|
||||
UV0_MASK = 0x0000F000,
|
||||
UV1_MASK = 0x000F0000,
|
||||
RGBA_MASK = 0x00F00000,
|
||||
|
||||
// Can add more here, such as a generic AUX or something. Don't know what to use it for though. Hardness for cloth sim?
|
||||
// Can add more here, such as a generic AUX or something. Don't know what to use it for though. Hardness for cloth sim?
|
||||
};
|
||||
|
||||
struct GLSLProgram;
|
||||
|
||||
+90
-91
@@ -10,22 +10,21 @@
|
||||
|
||||
// *image_data_ptr should be deleted with free()
|
||||
// return value of 1 == success.
|
||||
int pngLoad(const char *file, int *pwidth,
|
||||
int *pheight, unsigned char **image_data_ptr,
|
||||
bool flip) {
|
||||
if (flip)
|
||||
int pngLoad(const char *file, int *pwidth, int *pheight, unsigned char **image_data_ptr,
|
||||
bool flip) {
|
||||
if (flip)
|
||||
{
|
||||
ELOG("pngLoad: flip flag not supported, image will be loaded upside down");
|
||||
}
|
||||
|
||||
|
||||
int x,y,n;
|
||||
unsigned char *data = stbi_load(file, &x, &y, &n, 4); // 4 = force RGBA
|
||||
unsigned char *data = stbi_load(file, &x, &y, &n, 4); // 4 = force RGBA
|
||||
if (!data)
|
||||
return 0;
|
||||
|
||||
|
||||
*pwidth = x;
|
||||
*pheight = y;
|
||||
// ... process data if not NULL ...
|
||||
// ... process data if not NULL ...
|
||||
// ... x = width, y = height, n = # 8-bit components per pixel ...
|
||||
// ... replace '0' with '1'..'4' to force that many components per pixel
|
||||
// ... but 'n' will always be the number that it would have been if you said 0
|
||||
@@ -47,91 +46,91 @@ int pngLoad(const char *file, int *pwidth,
|
||||
// *image_data_ptr should be deleted with free()
|
||||
// return value of 1 == success.
|
||||
int pngLoad(const char *file, int *pwidth,
|
||||
int *pheight, unsigned char **image_data_ptr,
|
||||
bool flip) {
|
||||
FILE *infile = fopen(file, "rb");
|
||||
if (!infile) {
|
||||
printf("No such file: %s\n", file);
|
||||
return 0;
|
||||
}
|
||||
/* Check for the 8-byte signature */
|
||||
char sig[8]; /* PNG signature array */
|
||||
int len = fread(sig, 1, 8, infile);
|
||||
if (len != 8 || !png_check_sig((unsigned char *) sig, 8)) {
|
||||
fclose(infile);
|
||||
return 0;
|
||||
}
|
||||
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
if (!png_ptr) {
|
||||
fclose(infile);
|
||||
return 4; /* out of memory */
|
||||
}
|
||||
png_infop info_ptr = png_create_info_struct(png_ptr);
|
||||
if (!info_ptr) {
|
||||
png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL);
|
||||
fclose(infile);
|
||||
return 4; /* out of memory */
|
||||
}
|
||||
if (setjmp(png_jmpbuf(png_ptr))) {
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||
fclose(infile);
|
||||
return 0;
|
||||
}
|
||||
int *pheight, unsigned char **image_data_ptr,
|
||||
bool flip) {
|
||||
FILE *infile = fopen(file, "rb");
|
||||
if (!infile) {
|
||||
printf("No such file: %s\n", file);
|
||||
return 0;
|
||||
}
|
||||
/* Check for the 8-byte signature */
|
||||
char sig[8]; /* PNG signature array */
|
||||
int len = fread(sig, 1, 8, infile);
|
||||
if (len != 8 || !png_check_sig((unsigned char *) sig, 8)) {
|
||||
fclose(infile);
|
||||
return 0;
|
||||
}
|
||||
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
if (!png_ptr) {
|
||||
fclose(infile);
|
||||
return 4; /* out of memory */
|
||||
}
|
||||
png_infop info_ptr = png_create_info_struct(png_ptr);
|
||||
if (!info_ptr) {
|
||||
png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL);
|
||||
fclose(infile);
|
||||
return 4; /* out of memory */
|
||||
}
|
||||
if (setjmp(png_jmpbuf(png_ptr))) {
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||
fclose(infile);
|
||||
return 0;
|
||||
}
|
||||
|
||||
png_init_io(png_ptr, infile);
|
||||
png_set_sig_bytes(png_ptr, 8); // we already checked the sig bytes
|
||||
png_read_info(png_ptr, info_ptr);
|
||||
int bit_depth=0;
|
||||
int color_type=0;
|
||||
png_uint_32 width=0, height=0;
|
||||
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL);
|
||||
*pwidth = (int)width;
|
||||
*pheight = (int)height;
|
||||
// Set up some transforms. Always load RGBA.
|
||||
if (color_type & PNG_COLOR_MASK_ALPHA) {
|
||||
// png_set_strip_alpha(png_ptr);
|
||||
}
|
||||
if (bit_depth > 8) {
|
||||
png_set_strip_16(png_ptr);
|
||||
}
|
||||
if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
|
||||
png_set_gray_to_rgb(png_ptr);
|
||||
}
|
||||
if (color_type == PNG_COLOR_TYPE_PALETTE) {
|
||||
png_set_palette_to_rgb(png_ptr);
|
||||
}
|
||||
if (color_type == PNG_COLOR_TYPE_RGB) {
|
||||
png_set_filler(png_ptr, 255, PNG_FILLER_AFTER);
|
||||
}
|
||||
png_init_io(png_ptr, infile);
|
||||
png_set_sig_bytes(png_ptr, 8); // we already checked the sig bytes
|
||||
png_read_info(png_ptr, info_ptr);
|
||||
int bit_depth=0;
|
||||
int color_type=0;
|
||||
png_uint_32 width=0, height=0;
|
||||
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL);
|
||||
*pwidth = (int)width;
|
||||
*pheight = (int)height;
|
||||
// Set up some transforms. Always load RGBA.
|
||||
if (color_type & PNG_COLOR_MASK_ALPHA) {
|
||||
// png_set_strip_alpha(png_ptr);
|
||||
}
|
||||
if (bit_depth > 8) {
|
||||
png_set_strip_16(png_ptr);
|
||||
}
|
||||
if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
|
||||
png_set_gray_to_rgb(png_ptr);
|
||||
}
|
||||
if (color_type == PNG_COLOR_TYPE_PALETTE) {
|
||||
png_set_palette_to_rgb(png_ptr);
|
||||
}
|
||||
if (color_type == PNG_COLOR_TYPE_RGB) {
|
||||
png_set_filler(png_ptr, 255, PNG_FILLER_AFTER);
|
||||
}
|
||||
|
||||
// Update the png info struct.
|
||||
png_read_update_info(png_ptr, info_ptr);
|
||||
unsigned long rowbytes = png_get_rowbytes(png_ptr, info_ptr);
|
||||
unsigned char *image_data = NULL; /* raw png image data */
|
||||
if ((image_data = (unsigned char *) malloc(rowbytes * height))==NULL) {
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||
return 4;
|
||||
}
|
||||
png_bytepp row_pointers = NULL;
|
||||
if ((row_pointers = (png_bytepp)malloc(height*sizeof(png_bytep))) == NULL) {
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||
free(image_data);
|
||||
image_data = NULL;
|
||||
return 4;
|
||||
}
|
||||
if (flip) {
|
||||
for (unsigned long i = 0; i < height; ++i)
|
||||
row_pointers[height - 1 - i] = (png_byte *)(image_data + i*rowbytes);
|
||||
} else {
|
||||
for (unsigned long i = 0; i < height; ++i)
|
||||
row_pointers[i] = (png_byte *)(image_data + i*rowbytes);
|
||||
}
|
||||
png_read_image(png_ptr, row_pointers);
|
||||
free(row_pointers);
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||
fclose(infile);
|
||||
*image_data_ptr = image_data;
|
||||
return 1;
|
||||
// Update the png info struct.
|
||||
png_read_update_info(png_ptr, info_ptr);
|
||||
unsigned long rowbytes = png_get_rowbytes(png_ptr, info_ptr);
|
||||
unsigned char *image_data = NULL; /* raw png image data */
|
||||
if ((image_data = (unsigned char *) malloc(rowbytes * height))==NULL) {
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||
return 4;
|
||||
}
|
||||
png_bytepp row_pointers = NULL;
|
||||
if ((row_pointers = (png_bytepp)malloc(height*sizeof(png_bytep))) == NULL) {
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||
free(image_data);
|
||||
image_data = NULL;
|
||||
return 4;
|
||||
}
|
||||
if (flip) {
|
||||
for (unsigned long i = 0; i < height; ++i)
|
||||
row_pointers[height - 1 - i] = (png_byte *)(image_data + i*rowbytes);
|
||||
} else {
|
||||
for (unsigned long i = 0; i < height; ++i)
|
||||
row_pointers[i] = (png_byte *)(image_data + i*rowbytes);
|
||||
}
|
||||
png_read_image(png_ptr, row_pointers);
|
||||
free(row_pointers);
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||
fclose(infile);
|
||||
*image_data_ptr = image_data;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+108
-108
@@ -8,132 +8,132 @@
|
||||
#include "file/vfs.h"
|
||||
|
||||
int ezuncompress(unsigned char* pDest, long* pnDestLen, const unsigned char* pSrc, long nSrcLen) {
|
||||
z_stream stream;
|
||||
stream.next_in = (Bytef*)pSrc;
|
||||
stream.avail_in = (uInt)nSrcLen;
|
||||
/* Check for source > 64K on 16-bit machine: */
|
||||
if ((uLong)stream.avail_in != (uLong)nSrcLen) return Z_BUF_ERROR;
|
||||
z_stream stream;
|
||||
stream.next_in = (Bytef*)pSrc;
|
||||
stream.avail_in = (uInt)nSrcLen;
|
||||
/* Check for source > 64K on 16-bit machine: */
|
||||
if ((uLong)stream.avail_in != (uLong)nSrcLen) return Z_BUF_ERROR;
|
||||
|
||||
uInt destlen = (uInt)*pnDestLen;
|
||||
if ((uLong)destlen != (uLong)*pnDestLen) return Z_BUF_ERROR;
|
||||
stream.zalloc = (alloc_func)0;
|
||||
stream.zfree = (free_func)0;
|
||||
uInt destlen = (uInt)*pnDestLen;
|
||||
if ((uLong)destlen != (uLong)*pnDestLen) return Z_BUF_ERROR;
|
||||
stream.zalloc = (alloc_func)0;
|
||||
stream.zfree = (free_func)0;
|
||||
|
||||
int err = inflateInit(&stream);
|
||||
if (err != Z_OK) return err;
|
||||
int err = inflateInit(&stream);
|
||||
if (err != Z_OK) return err;
|
||||
|
||||
int nExtraChunks = 0;
|
||||
do {
|
||||
stream.next_out = pDest;
|
||||
stream.avail_out = destlen;
|
||||
err = inflate(&stream, Z_FINISH);
|
||||
if (err == Z_STREAM_END )
|
||||
break;
|
||||
if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0))
|
||||
err = Z_DATA_ERROR;
|
||||
if (err != Z_BUF_ERROR) {
|
||||
inflateEnd(&stream);
|
||||
return err;
|
||||
}
|
||||
nExtraChunks += 1;
|
||||
} while (stream.avail_out == 0);
|
||||
int nExtraChunks = 0;
|
||||
do {
|
||||
stream.next_out = pDest;
|
||||
stream.avail_out = destlen;
|
||||
err = inflate(&stream, Z_FINISH);
|
||||
if (err == Z_STREAM_END )
|
||||
break;
|
||||
if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0))
|
||||
err = Z_DATA_ERROR;
|
||||
if (err != Z_BUF_ERROR) {
|
||||
inflateEnd(&stream);
|
||||
return err;
|
||||
}
|
||||
nExtraChunks += 1;
|
||||
} while (stream.avail_out == 0);
|
||||
|
||||
*pnDestLen = stream.total_out;
|
||||
*pnDestLen = stream.total_out;
|
||||
|
||||
err = inflateEnd(&stream);
|
||||
if (err != Z_OK) return err;
|
||||
err = inflateEnd(&stream);
|
||||
if (err != Z_OK) return err;
|
||||
|
||||
return nExtraChunks ? Z_BUF_ERROR : Z_OK;
|
||||
return nExtraChunks ? Z_BUF_ERROR : Z_OK;
|
||||
}
|
||||
|
||||
static const char magic[5] = "ZIMG";
|
||||
|
||||
static unsigned int log2i(unsigned int val) {
|
||||
unsigned int ret = -1;
|
||||
while (val != 0) {
|
||||
val >>= 1; ret++;
|
||||
}
|
||||
return ret;
|
||||
unsigned int ret = -1;
|
||||
while (val != 0) {
|
||||
val >>= 1; ret++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int LoadZIMPtr(uint8_t *zim, int datasize, int *width, int *height, int *flags, uint8 **image) {
|
||||
if (zim[0] != 'Z' || zim[1] != 'I' || zim[2] != 'M' || zim[3] != 'G') {
|
||||
ELOG("Not a ZIM file");
|
||||
return 0;
|
||||
}
|
||||
memcpy(width, zim + 4, 4);
|
||||
memcpy(height, zim + 8, 4);
|
||||
memcpy(flags, zim + 12, 4);
|
||||
if (zim[0] != 'Z' || zim[1] != 'I' || zim[2] != 'M' || zim[3] != 'G') {
|
||||
ELOG("Not a ZIM file");
|
||||
return 0;
|
||||
}
|
||||
memcpy(width, zim + 4, 4);
|
||||
memcpy(height, zim + 8, 4);
|
||||
memcpy(flags, zim + 12, 4);
|
||||
|
||||
int num_levels = 1;
|
||||
int image_data_size[ZIM_MAX_MIP_LEVELS];
|
||||
if (*flags & ZIM_HAS_MIPS) {
|
||||
num_levels = log2i(*width < *height ? *width : *height) + 1;
|
||||
}
|
||||
int total_data_size = 0;
|
||||
for (int i = 0; i < num_levels; i++) {
|
||||
if (i > 0) {
|
||||
width[i] = width[i-1] / 2;
|
||||
height[i] = height[i-1] / 2;
|
||||
}
|
||||
switch (*flags & ZIM_FORMAT_MASK) {
|
||||
case ZIM_RGBA8888:
|
||||
image_data_size[i] = width[i] * height[i] * 4;
|
||||
break;
|
||||
case ZIM_RGBA4444:
|
||||
case ZIM_RGB565:
|
||||
image_data_size[i] = width[i] * height[i] * 2;
|
||||
break;
|
||||
case ZIM_ETC1:
|
||||
{
|
||||
int data_width = width[i];
|
||||
int data_height = height[i];
|
||||
if (data_width < 4) data_width = 4;
|
||||
if (data_height < 4) data_height = 4;
|
||||
image_data_size[i] = data_width * data_height / 2;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ELOG("Invalid ZIM format %i", *flags & ZIM_FORMAT_MASK);
|
||||
return 0;
|
||||
}
|
||||
total_data_size += image_data_size[i];
|
||||
}
|
||||
int num_levels = 1;
|
||||
int image_data_size[ZIM_MAX_MIP_LEVELS];
|
||||
if (*flags & ZIM_HAS_MIPS) {
|
||||
num_levels = log2i(*width < *height ? *width : *height) + 1;
|
||||
}
|
||||
int total_data_size = 0;
|
||||
for (int i = 0; i < num_levels; i++) {
|
||||
if (i > 0) {
|
||||
width[i] = width[i-1] / 2;
|
||||
height[i] = height[i-1] / 2;
|
||||
}
|
||||
switch (*flags & ZIM_FORMAT_MASK) {
|
||||
case ZIM_RGBA8888:
|
||||
image_data_size[i] = width[i] * height[i] * 4;
|
||||
break;
|
||||
case ZIM_RGBA4444:
|
||||
case ZIM_RGB565:
|
||||
image_data_size[i] = width[i] * height[i] * 2;
|
||||
break;
|
||||
case ZIM_ETC1:
|
||||
{
|
||||
int data_width = width[i];
|
||||
int data_height = height[i];
|
||||
if (data_width < 4) data_width = 4;
|
||||
if (data_height < 4) data_height = 4;
|
||||
image_data_size[i] = data_width * data_height / 2;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ELOG("Invalid ZIM format %i", *flags & ZIM_FORMAT_MASK);
|
||||
return 0;
|
||||
}
|
||||
total_data_size += image_data_size[i];
|
||||
}
|
||||
|
||||
image[0] = (uint8 *)malloc(total_data_size);
|
||||
for (int i = 1; i < num_levels; i++) {
|
||||
image[i] = image[i-1] + image_data_size[i-1];
|
||||
}
|
||||
image[0] = (uint8 *)malloc(total_data_size);
|
||||
for (int i = 1; i < num_levels; i++) {
|
||||
image[i] = image[i-1] + image_data_size[i-1];
|
||||
}
|
||||
|
||||
if (*flags & ZIM_ZLIB_COMPRESSED) {
|
||||
long outlen = total_data_size;
|
||||
if (Z_OK != ezuncompress(*image, &outlen, (unsigned char *)(zim + 16), datasize - 16)) {
|
||||
free(*image);
|
||||
*image = 0;
|
||||
return 0;
|
||||
}
|
||||
if (outlen != total_data_size) {
|
||||
ELOG("Wrong size data in ZIM: %i vs %i", (int)outlen, (int)total_data_size);
|
||||
}
|
||||
} else {
|
||||
memcpy(*image, zim + 16, datasize - 16);
|
||||
if (datasize - 16 != total_data_size) {
|
||||
ELOG("Wrong size data in ZIM: %i vs %i", (int)(datasize-16), (int)total_data_size);
|
||||
}
|
||||
}
|
||||
return num_levels;
|
||||
if (*flags & ZIM_ZLIB_COMPRESSED) {
|
||||
long outlen = total_data_size;
|
||||
if (Z_OK != ezuncompress(*image, &outlen, (unsigned char *)(zim + 16), datasize - 16)) {
|
||||
free(*image);
|
||||
*image = 0;
|
||||
return 0;
|
||||
}
|
||||
if (outlen != total_data_size) {
|
||||
ELOG("Wrong size data in ZIM: %i vs %i", (int)outlen, (int)total_data_size);
|
||||
}
|
||||
} else {
|
||||
memcpy(*image, zim + 16, datasize - 16);
|
||||
if (datasize - 16 != total_data_size) {
|
||||
ELOG("Wrong size data in ZIM: %i vs %i", (int)(datasize-16), (int)total_data_size);
|
||||
}
|
||||
}
|
||||
return num_levels;
|
||||
}
|
||||
|
||||
int LoadZIM(const char *filename, int *width, int *height, int *format, uint8_t **image) {
|
||||
size_t size;
|
||||
uint8_t *buffer = VFSReadFile(filename, &size);
|
||||
if (!buffer) {
|
||||
return 0;
|
||||
}
|
||||
int retval = LoadZIMPtr(buffer, size, width, height, format, image);
|
||||
if (!retval) {
|
||||
ELOG("Not a valid ZIM file: %s", filename);
|
||||
}
|
||||
delete [] buffer;
|
||||
return retval;
|
||||
size_t size;
|
||||
uint8_t *buffer = VFSReadFile(filename, &size);
|
||||
if (!buffer) {
|
||||
return 0;
|
||||
}
|
||||
int retval = LoadZIMPtr(buffer, size, width, height, format, image);
|
||||
if (!retval) {
|
||||
ELOG("Not a valid ZIM file: %s", filename);
|
||||
}
|
||||
delete [] buffer;
|
||||
return retval;
|
||||
}
|
||||
|
||||
+16
-16
@@ -18,26 +18,26 @@
|
||||
// Defined flags:
|
||||
|
||||
enum {
|
||||
ZIM_RGBA8888 = 0, // Assumed format if no other format is set
|
||||
ZIM_RGBA4444 = 1, // GL_UNSIGNED_SHORT_4_4_4_4
|
||||
ZIM_RGB565 = 2, // GL_UNSIGNED_SHORT_5_6_5
|
||||
ZIM_ETC1 = 3,
|
||||
ZIM_RGB888 = 4,
|
||||
ZIM_LUMINANCE_ALPHA = 5,
|
||||
ZIM_LUMINANCE = 6,
|
||||
ZIM_ALPHA = 7,
|
||||
// There's space for plenty more formats.
|
||||
ZIM_FORMAT_MASK = 15,
|
||||
ZIM_HAS_MIPS = 16, // If set, assumes that a full mip chain is present. Mips are zlib-compressed individually and stored in sequence. Always half sized.
|
||||
ZIM_GEN_MIPS = 32, // If set, the caller is advised to automatically generate mips. (maybe later, the ZIM lib will generate the mips for you).
|
||||
ZIM_DITHER = 64, // If set, dithers during save if color reduction is necessary.
|
||||
ZIM_CLAMP = 128, // Texture should default to clamp instead of wrap.
|
||||
ZIM_ZLIB_COMPRESSED = 256,
|
||||
ZIM_RGBA8888 = 0, // Assumed format if no other format is set
|
||||
ZIM_RGBA4444 = 1, // GL_UNSIGNED_SHORT_4_4_4_4
|
||||
ZIM_RGB565 = 2, // GL_UNSIGNED_SHORT_5_6_5
|
||||
ZIM_ETC1 = 3,
|
||||
ZIM_RGB888 = 4,
|
||||
ZIM_LUMINANCE_ALPHA = 5,
|
||||
ZIM_LUMINANCE = 6,
|
||||
ZIM_ALPHA = 7,
|
||||
// There's space for plenty more formats.
|
||||
ZIM_FORMAT_MASK = 15,
|
||||
ZIM_HAS_MIPS = 16, // If set, assumes that a full mip chain is present. Mips are zlib-compressed individually and stored in sequence. Always half sized.
|
||||
ZIM_GEN_MIPS = 32, // If set, the caller is advised to automatically generate mips. (maybe later, the ZIM lib will generate the mips for you).
|
||||
ZIM_DITHER = 64, // If set, dithers during save if color reduction is necessary.
|
||||
ZIM_CLAMP = 128, // Texture should default to clamp instead of wrap.
|
||||
ZIM_ZLIB_COMPRESSED = 256,
|
||||
};
|
||||
|
||||
// ZIM will only ever support up to 12 levels (4096x4096 max).
|
||||
enum {
|
||||
ZIM_MAX_MIP_LEVELS = 12,
|
||||
ZIM_MAX_MIP_LEVELS = 12,
|
||||
};
|
||||
|
||||
// Delete the returned pointer using free()
|
||||
|
||||
+194
-194
@@ -12,55 +12,55 @@ if (flags & ZIM_HAS_MIPS) {
|
||||
num_levels = log2i(width > height ? width : height);
|
||||
}*/
|
||||
static unsigned int log2i(unsigned int val) {
|
||||
unsigned int ret = -1;
|
||||
while (val != 0) {
|
||||
val >>= 1; ret++;
|
||||
}
|
||||
return ret;
|
||||
unsigned int ret = -1;
|
||||
while (val != 0) {
|
||||
val >>= 1; ret++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int ezcompress(unsigned char* pDest, long* pnDestLen, const unsigned char* pSrc, long nSrcLen) {
|
||||
z_stream stream;
|
||||
int err;
|
||||
z_stream stream;
|
||||
int err;
|
||||
|
||||
int nExtraChunks;
|
||||
uInt destlen;
|
||||
int nExtraChunks;
|
||||
uInt destlen;
|
||||
|
||||
stream.next_in = (Bytef*)pSrc;
|
||||
stream.avail_in = (uInt)nSrcLen;
|
||||
stream.next_in = (Bytef*)pSrc;
|
||||
stream.avail_in = (uInt)nSrcLen;
|
||||
#ifdef MAXSEG_64K
|
||||
/* Check for source > 64K on 16-bit machine: */
|
||||
if ((uLong)stream.avail_in != nSrcLen) return Z_BUF_ERROR;
|
||||
/* Check for source > 64K on 16-bit machine: */
|
||||
if ((uLong)stream.avail_in != nSrcLen) return Z_BUF_ERROR;
|
||||
#endif
|
||||
destlen = (uInt)*pnDestLen;
|
||||
if ((uLong)destlen != (uLong)*pnDestLen) return Z_BUF_ERROR;
|
||||
stream.zalloc = (alloc_func)0;
|
||||
stream.zfree = (free_func)0;
|
||||
stream.opaque = (voidpf)0;
|
||||
destlen = (uInt)*pnDestLen;
|
||||
if ((uLong)destlen != (uLong)*pnDestLen) return Z_BUF_ERROR;
|
||||
stream.zalloc = (alloc_func)0;
|
||||
stream.zfree = (free_func)0;
|
||||
stream.opaque = (voidpf)0;
|
||||
|
||||
err = deflateInit(&stream, Z_DEFAULT_COMPRESSION);
|
||||
if (err != Z_OK) return err;
|
||||
nExtraChunks = 0;
|
||||
do {
|
||||
stream.next_out = pDest;
|
||||
stream.avail_out = destlen;
|
||||
err = deflate(&stream, Z_FINISH);
|
||||
if (err == Z_STREAM_END )
|
||||
break;
|
||||
if (err != Z_OK) {
|
||||
deflateEnd(&stream);
|
||||
return err;
|
||||
}
|
||||
nExtraChunks += 1;
|
||||
} while (stream.avail_out == 0);
|
||||
err = deflateInit(&stream, Z_DEFAULT_COMPRESSION);
|
||||
if (err != Z_OK) return err;
|
||||
nExtraChunks = 0;
|
||||
do {
|
||||
stream.next_out = pDest;
|
||||
stream.avail_out = destlen;
|
||||
err = deflate(&stream, Z_FINISH);
|
||||
if (err == Z_STREAM_END )
|
||||
break;
|
||||
if (err != Z_OK) {
|
||||
deflateEnd(&stream);
|
||||
return err;
|
||||
}
|
||||
nExtraChunks += 1;
|
||||
} while (stream.avail_out == 0);
|
||||
|
||||
*pnDestLen = stream.total_out;
|
||||
*pnDestLen = stream.total_out;
|
||||
|
||||
err = deflateEnd(&stream);
|
||||
if (err != Z_OK) return err;
|
||||
err = deflateEnd(&stream);
|
||||
if (err != Z_OK) return err;
|
||||
|
||||
return nExtraChunks ? Z_BUF_ERROR : Z_OK;
|
||||
return nExtraChunks ? Z_BUF_ERROR : Z_OK;
|
||||
}
|
||||
|
||||
inline int clamp16(int x) { if (x < 0) return 0; if (x > 15) return 15; return x; }
|
||||
@@ -69,179 +69,179 @@ inline int clamp64(int x) { if (x < 0) return 0; if (x > 63) return 63; return x
|
||||
|
||||
|
||||
bool ispowerof2 (int x) {
|
||||
if (!x || (x&(x-1)))
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
if (!x || (x&(x-1)))
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Convert(const uint8_t *image_data, int width, int height, int pitch, int flags,
|
||||
uint8_t **data, int *data_size) {
|
||||
// For 4444 and 565. Ordered dither matrix. looks really surprisingly good on cell phone screens at 4444.
|
||||
int dith[16] = {
|
||||
1, 9, 3, 11,
|
||||
13, 5, 15, 7,
|
||||
4, 12, 2, 10,
|
||||
16, 8, 14, 6
|
||||
};
|
||||
if ((flags & ZIM_DITHER) == 0) {
|
||||
for (int i = 0; i < 16; i++) { dith[i] = 8; }
|
||||
}
|
||||
switch (flags & ZIM_FORMAT_MASK) {
|
||||
case ZIM_RGBA8888:
|
||||
{
|
||||
*data_size = width * height * 4;
|
||||
*data = new uint8_t[width * height * 4];
|
||||
for (int y = 0; y < height; y++) {
|
||||
memcpy((*data) + y * width * 4, image_data + y * pitch, width * 4);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ZIM_ETC1: {
|
||||
// Check for power of 2
|
||||
if (!ispowerof2(width) || !ispowerof2(height)) {
|
||||
FLOG("Image must have power of 2 dimensions, %ix%i just isn't that.", width, height);
|
||||
}
|
||||
// Convert RGBX to ETC1 before saving.
|
||||
int blockw = width/4;
|
||||
int blockh = height/4;
|
||||
*data_size = blockw * blockh * 8;
|
||||
*data = new uint8_t[*data_size];
|
||||
uint8_t **data, int *data_size) {
|
||||
// For 4444 and 565. Ordered dither matrix. looks really surprisingly good on cell phone screens at 4444.
|
||||
int dith[16] = {
|
||||
1, 9, 3, 11,
|
||||
13, 5, 15, 7,
|
||||
4, 12, 2, 10,
|
||||
16, 8, 14, 6
|
||||
};
|
||||
if ((flags & ZIM_DITHER) == 0) {
|
||||
for (int i = 0; i < 16; i++) { dith[i] = 8; }
|
||||
}
|
||||
switch (flags & ZIM_FORMAT_MASK) {
|
||||
case ZIM_RGBA8888:
|
||||
{
|
||||
*data_size = width * height * 4;
|
||||
*data = new uint8_t[width * height * 4];
|
||||
for (int y = 0; y < height; y++) {
|
||||
memcpy((*data) + y * width * 4, image_data + y * pitch, width * 4);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ZIM_ETC1: {
|
||||
// Check for power of 2
|
||||
if (!ispowerof2(width) || !ispowerof2(height)) {
|
||||
FLOG("Image must have power of 2 dimensions, %ix%i just isn't that.", width, height);
|
||||
}
|
||||
// Convert RGBX to ETC1 before saving.
|
||||
int blockw = width/4;
|
||||
int blockh = height/4;
|
||||
*data_size = blockw * blockh * 8;
|
||||
*data = new uint8_t[*data_size];
|
||||
#pragma omp parallel for
|
||||
for (int y = 0; y < blockh; y++) {
|
||||
for (int x = 0; x < blockw; x++) {
|
||||
CompressBlock(image_data + ((y * 4) * (pitch/4) + x * 4) * 4, width,
|
||||
(*data) + (blockw * y + x) * 8, 1);
|
||||
}
|
||||
}
|
||||
width = blockw * 4;
|
||||
height = blockh * 4;
|
||||
break;
|
||||
}
|
||||
case ZIM_RGBA4444:
|
||||
{
|
||||
*data_size = width * height * 2;
|
||||
*data = new uint8_t[*data_size];
|
||||
uint16_t *dst = (uint16_t *)(*data);
|
||||
int i = 0;
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
int dithval = dith[(x&3)+((y&0x3)<<2)] - 8;
|
||||
int r = clamp16((image_data[i * 4] + dithval) >> 4);
|
||||
int g = clamp16((image_data[i * 4 + 1] + dithval) >> 4);
|
||||
int b = clamp16((image_data[i * 4 + 2] + dithval) >> 4);
|
||||
int a = clamp16((image_data[i * 4 + 3] + dithval) >> 4); // really dither alpha?
|
||||
// Note: GL_UNSIGNED_SHORT_4_4_4_4, not GL_UNSIGNED_SHORT_4_4_4_4_REV
|
||||
*dst++ = (r << 12) | (g << 8) | (b << 4) | (a << 0);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ZIM_RGB565:
|
||||
{
|
||||
*data_size = width * height * 2;
|
||||
*data = new uint8_t[*data_size];
|
||||
uint16_t *dst = (uint16_t *)(*data);
|
||||
int i = 0;
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
int dithval = dith[(x&3)+((y&0x3)<<2)] - 8;
|
||||
dithval = 0;
|
||||
int r = clamp32((image_data[i * 4] + dithval/2) >> 3);
|
||||
int g = clamp64((image_data[i * 4 + 1] + dithval/4) >> 2);
|
||||
int b = clamp32((image_data[i * 4 + 2] + dithval/2) >> 3);
|
||||
// Note: GL_UNSIGNED_SHORT_5_6_5, not GL_UNSIGNED_SHORT_5_6_5_REV
|
||||
*dst++ = (r << 11) | (g << 5) | (b);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
for (int y = 0; y < blockh; y++) {
|
||||
for (int x = 0; x < blockw; x++) {
|
||||
CompressBlock(image_data + ((y * 4) * (pitch/4) + x * 4) * 4, width,
|
||||
(*data) + (blockw * y + x) * 8, 1);
|
||||
}
|
||||
}
|
||||
width = blockw * 4;
|
||||
height = blockh * 4;
|
||||
break;
|
||||
}
|
||||
case ZIM_RGBA4444:
|
||||
{
|
||||
*data_size = width * height * 2;
|
||||
*data = new uint8_t[*data_size];
|
||||
uint16_t *dst = (uint16_t *)(*data);
|
||||
int i = 0;
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
int dithval = dith[(x&3)+((y&0x3)<<2)] - 8;
|
||||
int r = clamp16((image_data[i * 4] + dithval) >> 4);
|
||||
int g = clamp16((image_data[i * 4 + 1] + dithval) >> 4);
|
||||
int b = clamp16((image_data[i * 4 + 2] + dithval) >> 4);
|
||||
int a = clamp16((image_data[i * 4 + 3] + dithval) >> 4); // really dither alpha?
|
||||
// Note: GL_UNSIGNED_SHORT_4_4_4_4, not GL_UNSIGNED_SHORT_4_4_4_4_REV
|
||||
*dst++ = (r << 12) | (g << 8) | (b << 4) | (a << 0);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ZIM_RGB565:
|
||||
{
|
||||
*data_size = width * height * 2;
|
||||
*data = new uint8_t[*data_size];
|
||||
uint16_t *dst = (uint16_t *)(*data);
|
||||
int i = 0;
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
int dithval = dith[(x&3)+((y&0x3)<<2)] - 8;
|
||||
dithval = 0;
|
||||
int r = clamp32((image_data[i * 4] + dithval/2) >> 3);
|
||||
int g = clamp64((image_data[i * 4 + 1] + dithval/4) >> 2);
|
||||
int b = clamp32((image_data[i * 4 + 2] + dithval/2) >> 3);
|
||||
// Note: GL_UNSIGNED_SHORT_5_6_5, not GL_UNSIGNED_SHORT_5_6_5_REV
|
||||
*dst++ = (r << 11) | (g << 5) | (b);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ELOG("Unhandled ZIM format %i", flags & ZIM_FORMAT_MASK);
|
||||
*data = 0;
|
||||
*data_size = 0;
|
||||
return;
|
||||
}
|
||||
default:
|
||||
ELOG("Unhandled ZIM format %i", flags & ZIM_FORMAT_MASK);
|
||||
*data = 0;
|
||||
*data_size = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Deletes the old buffer.
|
||||
uint8_t *DownsampleBy2(const uint8_t *image, int width, int height, int pitch) {
|
||||
uint8_t *out = new uint8_t[(width/2) * (height/2) * 4];
|
||||
uint8_t *out = new uint8_t[(width/2) * (height/2) * 4];
|
||||
|
||||
int degamma[256];
|
||||
int gamma[32768];
|
||||
for (int i =0; i < 256; i++) {
|
||||
degamma[i] = powf((float)i / 255.0f, 1.0f/2.2f) * 8191.0f;
|
||||
}
|
||||
for (int i = 0; i < 32768; i++) {
|
||||
gamma[i] = powf((float)i / 32764.0f, 2.2f) * 255.0f;
|
||||
}
|
||||
int degamma[256];
|
||||
int gamma[32768];
|
||||
for (int i =0; i < 256; i++) {
|
||||
degamma[i] = powf((float)i / 255.0f, 1.0f/2.2f) * 8191.0f;
|
||||
}
|
||||
for (int i = 0; i < 32768; i++) {
|
||||
gamma[i] = powf((float)i / 32764.0f, 2.2f) * 255.0f;
|
||||
}
|
||||
|
||||
// Really stupid mipmap downsampling - at least it does gamma though.
|
||||
for (int y = 0; y < height; y+=2) {
|
||||
for (int x = 0; x < width; x+=2) {
|
||||
const uint8_t *tl = image + pitch * y + x*4;
|
||||
const uint8_t *tr = tl + 4;
|
||||
const uint8_t *bl = tl + pitch;
|
||||
const uint8_t *br = bl + 4;
|
||||
uint8_t *d = out + ((y/2) * ((width/2)) + x / 2) * 4;
|
||||
for (int c = 0; c < 4; c++) {
|
||||
d[c] = gamma[degamma[tl[c]] + degamma[tr[c]] + degamma[bl[c]] + degamma[br[c]]];
|
||||
}
|
||||
}
|
||||
}
|
||||
return out;
|
||||
// Really stupid mipmap downsampling - at least it does gamma though.
|
||||
for (int y = 0; y < height; y+=2) {
|
||||
for (int x = 0; x < width; x+=2) {
|
||||
const uint8_t *tl = image + pitch * y + x*4;
|
||||
const uint8_t *tr = tl + 4;
|
||||
const uint8_t *bl = tl + pitch;
|
||||
const uint8_t *br = bl + 4;
|
||||
uint8_t *d = out + ((y/2) * ((width/2)) + x / 2) * 4;
|
||||
for (int c = 0; c < 4; c++) {
|
||||
d[c] = gamma[degamma[tl[c]] + degamma[tr[c]] + degamma[bl[c]] + degamma[br[c]]];
|
||||
}
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
void SaveZIM(const char *filename, int width, int height, int pitch, int flags, const uint8_t *image_data) {
|
||||
FILE *f = fopen(filename, "wb");
|
||||
fwrite(magic, 1, 4, f);
|
||||
fwrite(&width, 1, 4, f);
|
||||
fwrite(&height, 1, 4, f);
|
||||
fwrite(&flags, 1, 4, f);
|
||||
FILE *f = fopen(filename, "wb");
|
||||
fwrite(magic, 1, 4, f);
|
||||
fwrite(&width, 1, 4, f);
|
||||
fwrite(&height, 1, 4, f);
|
||||
fwrite(&flags, 1, 4, f);
|
||||
|
||||
int num_levels = 1;
|
||||
if (flags & ZIM_HAS_MIPS) {
|
||||
num_levels = log2i(width > height ? height : width) + 1;
|
||||
}
|
||||
for (int i = 0; i < num_levels; i++) {
|
||||
uint8_t *data = 0;
|
||||
int data_size;
|
||||
Convert(image_data, width, height, pitch, flags, &data, &data_size);
|
||||
if (flags & ZIM_ZLIB_COMPRESSED) {
|
||||
long dest_len = data_size * 2;
|
||||
uint8_t *dest = new uint8_t[dest_len];
|
||||
if (Z_OK == ezcompress(dest, &dest_len, data, data_size)) {
|
||||
fwrite(dest, 1, dest_len, f);
|
||||
} else {
|
||||
ELOG("Zlib compression failed.\n");
|
||||
}
|
||||
delete [] dest;
|
||||
} else {
|
||||
fwrite(data, 1, data_size, f);
|
||||
}
|
||||
delete [] data;
|
||||
int num_levels = 1;
|
||||
if (flags & ZIM_HAS_MIPS) {
|
||||
num_levels = log2i(width > height ? height : width) + 1;
|
||||
}
|
||||
for (int i = 0; i < num_levels; i++) {
|
||||
uint8_t *data = 0;
|
||||
int data_size;
|
||||
Convert(image_data, width, height, pitch, flags, &data, &data_size);
|
||||
if (flags & ZIM_ZLIB_COMPRESSED) {
|
||||
long dest_len = data_size * 2;
|
||||
uint8_t *dest = new uint8_t[dest_len];
|
||||
if (Z_OK == ezcompress(dest, &dest_len, data, data_size)) {
|
||||
fwrite(dest, 1, dest_len, f);
|
||||
} else {
|
||||
ELOG("Zlib compression failed.\n");
|
||||
}
|
||||
delete [] dest;
|
||||
} else {
|
||||
fwrite(data, 1, data_size, f);
|
||||
}
|
||||
delete [] data;
|
||||
|
||||
if (i != num_levels - 1) {
|
||||
uint8_t *smaller = DownsampleBy2(image_data, width, height, pitch);
|
||||
if (i != 0) {
|
||||
delete [] image_data;
|
||||
}
|
||||
image_data = smaller;
|
||||
width /= 2;
|
||||
height /= 2;
|
||||
if ((flags & ZIM_FORMAT_MASK) == ZIM_ETC1) {
|
||||
if (width < 4) width = 4;
|
||||
if (height < 4) height = 4;
|
||||
}
|
||||
pitch = width * 4;
|
||||
}
|
||||
}
|
||||
delete [] image_data;
|
||||
fclose(f);
|
||||
if (i != num_levels - 1) {
|
||||
uint8_t *smaller = DownsampleBy2(image_data, width, height, pitch);
|
||||
if (i != 0) {
|
||||
delete [] image_data;
|
||||
}
|
||||
image_data = smaller;
|
||||
width /= 2;
|
||||
height /= 2;
|
||||
if ((flags & ZIM_FORMAT_MASK) == ZIM_ETC1) {
|
||||
if (width < 4) width = 4;
|
||||
if (height < 4) height = 4;
|
||||
}
|
||||
pitch = width * 4;
|
||||
}
|
||||
}
|
||||
delete [] image_data;
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
+38
-38
@@ -7,17 +7,17 @@
|
||||
namespace GestureDetector {
|
||||
|
||||
struct Finger {
|
||||
bool down;
|
||||
float X;
|
||||
float Y;
|
||||
float lastX;
|
||||
float lastY;
|
||||
float downX;
|
||||
float downY;
|
||||
float deltaX;
|
||||
float deltaY;
|
||||
float smoothDeltaX;
|
||||
float smoothDeltaY;
|
||||
bool down;
|
||||
float X;
|
||||
float Y;
|
||||
float lastX;
|
||||
float lastY;
|
||||
float downX;
|
||||
float downY;
|
||||
float deltaX;
|
||||
float deltaY;
|
||||
float smoothDeltaX;
|
||||
float smoothDeltaY;
|
||||
};
|
||||
|
||||
// State
|
||||
@@ -26,46 +26,46 @@ struct Finger {
|
||||
static Finger fingers[MAX_FINGERS];
|
||||
|
||||
void update(const InputState &state) {
|
||||
// Mouse / 1-finger-touch control.
|
||||
if (state.pointer_down[0]) {
|
||||
fingers[0].down = true;
|
||||
fingers[0].downX = state.pointer_x[0];
|
||||
fingers[0].downY = state.pointer_y[0];
|
||||
} else {
|
||||
fingers[0].down = false;
|
||||
}
|
||||
// Mouse / 1-finger-touch control.
|
||||
if (state.pointer_down[0]) {
|
||||
fingers[0].down = true;
|
||||
fingers[0].downX = state.pointer_x[0];
|
||||
fingers[0].downY = state.pointer_y[0];
|
||||
} else {
|
||||
fingers[0].down = false;
|
||||
}
|
||||
|
||||
fingers[0].lastX = fingers[0].X;
|
||||
fingers[0].lastY = fingers[0].Y;
|
||||
fingers[0].lastX = fingers[0].X;
|
||||
fingers[0].lastY = fingers[0].Y;
|
||||
|
||||
// TODO: real multitouch
|
||||
// TODO: real multitouch
|
||||
}
|
||||
|
||||
bool down(int i, float *xdelta, float *ydelta) {
|
||||
if (!fingers[i].down) {
|
||||
return false;
|
||||
}
|
||||
*xdelta = fingers[i].downX;
|
||||
*ydelta = fingers[i].downY;
|
||||
return true;
|
||||
if (!fingers[i].down) {
|
||||
return false;
|
||||
}
|
||||
*xdelta = fingers[i].downX;
|
||||
*ydelta = fingers[i].downY;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dragDistance(int i, float *xdelta, float *ydelta) {
|
||||
if (!fingers[i].down)
|
||||
return false;
|
||||
if (!fingers[i].down)
|
||||
return false;
|
||||
|
||||
*xdelta = fingers[i].X - fingers[i].downX;
|
||||
*ydelta = fingers[i].Y - fingers[i].downY;
|
||||
return true;
|
||||
*xdelta = fingers[i].X - fingers[i].downX;
|
||||
*ydelta = fingers[i].Y - fingers[i].downY;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dragDelta(int i, float *xdelta, float *ydelta) {
|
||||
if (!fingers[i].down)
|
||||
return false;
|
||||
if (!fingers[i].down)
|
||||
return false;
|
||||
|
||||
*xdelta = fingers[i].X - fingers[i].lastX;
|
||||
*ydelta = fingers[i].Y - fingers[i].lastY;
|
||||
return true;
|
||||
*xdelta = fingers[i].X - fingers[i].lastX;
|
||||
*ydelta = fingers[i].Y - fingers[i].lastY;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,17 +5,17 @@
|
||||
|
||||
namespace GestureDetector
|
||||
{
|
||||
void update(const InputState &state);
|
||||
void update(const InputState &state);
|
||||
|
||||
bool down(int finger, float *xdown, float *ydown);
|
||||
bool down(int finger, float *xdown, float *ydown);
|
||||
|
||||
// x/ydelta is difference from current location to the start of the drag.
|
||||
// Returns true if button/finger is down, for convenience.
|
||||
bool dragDistance(int finger, float *xdelta, float *ydelta);
|
||||
|
||||
// x/ydelta is (smoothed?) difference from current location to the position from the last frame.
|
||||
// Returns true if button/finger is down, for convenience.
|
||||
bool dragDelta(int finger, float *xdelta, float *ydelta);
|
||||
// x/ydelta is difference from current location to the start of the drag.
|
||||
// Returns true if button/finger is down, for convenience.
|
||||
bool dragDistance(int finger, float *xdelta, float *ydelta);
|
||||
|
||||
// x/ydelta is (smoothed?) difference from current location to the position from the last frame.
|
||||
// Returns true if button/finger is down, for convenience.
|
||||
bool dragDelta(int finger, float *xdelta, float *ydelta);
|
||||
|
||||
|
||||
};
|
||||
|
||||
+48
-48
@@ -5,18 +5,18 @@
|
||||
#include "base/basictypes.h"
|
||||
|
||||
enum {
|
||||
PAD_BUTTON_A = 1,
|
||||
PAD_BUTTON_B = 2,
|
||||
PAD_BUTTON_X = 4,
|
||||
PAD_BUTTON_Y = 8,
|
||||
PAD_BUTTON_LBUMPER = 16,
|
||||
PAD_BUTTON_RBUMPER = 32,
|
||||
PAD_BUTTON_START = 64,
|
||||
PAD_BUTTON_SELECT = 128,
|
||||
PAD_BUTTON_UP = 256,
|
||||
PAD_BUTTON_DOWN = 512,
|
||||
PAD_BUTTON_LEFT = 1024,
|
||||
PAD_BUTTON_RIGHT = 2048,
|
||||
PAD_BUTTON_A = 1,
|
||||
PAD_BUTTON_B = 2,
|
||||
PAD_BUTTON_X = 4,
|
||||
PAD_BUTTON_Y = 8,
|
||||
PAD_BUTTON_LBUMPER = 16,
|
||||
PAD_BUTTON_RBUMPER = 32,
|
||||
PAD_BUTTON_START = 64,
|
||||
PAD_BUTTON_SELECT = 128,
|
||||
PAD_BUTTON_UP = 256,
|
||||
PAD_BUTTON_DOWN = 512,
|
||||
PAD_BUTTON_LEFT = 1024,
|
||||
PAD_BUTTON_RIGHT = 2048,
|
||||
|
||||
// Android only
|
||||
PAD_BUTTON_MENU = 4096,
|
||||
@@ -26,55 +26,55 @@ enum {
|
||||
#ifndef MAX_POINTERS
|
||||
#define MAX_POINTERS 8
|
||||
#endif
|
||||
|
||||
|
||||
// Agglomeration of all possible inputs, and automatically computed
|
||||
// deltas where applicable.
|
||||
struct InputState {
|
||||
// Lock this whenever you access the data in this struct.
|
||||
mutable recursive_mutex lock;
|
||||
InputState()
|
||||
: pad_buttons(0),
|
||||
pad_last_buttons(0),
|
||||
pad_buttons_down(0),
|
||||
pad_buttons_up(0),
|
||||
mouse_valid(false),
|
||||
accelerometer_valid(false) {
|
||||
memset(pointer_down, 0, sizeof(pointer_down));
|
||||
}
|
||||
// Lock this whenever you access the data in this struct.
|
||||
mutable recursive_mutex lock;
|
||||
InputState()
|
||||
: pad_buttons(0),
|
||||
pad_last_buttons(0),
|
||||
pad_buttons_down(0),
|
||||
pad_buttons_up(0),
|
||||
mouse_valid(false),
|
||||
accelerometer_valid(false) {
|
||||
memset(pointer_down, 0, sizeof(pointer_down));
|
||||
}
|
||||
|
||||
// Gamepad style input
|
||||
int pad_buttons; // bitfield
|
||||
int pad_last_buttons;
|
||||
int pad_buttons_down; // buttons just pressed this frame
|
||||
int pad_buttons_up; // buttons just pressed last frame
|
||||
float pad_lstick_x;
|
||||
float pad_lstick_y;
|
||||
float pad_rstick_x;
|
||||
float pad_rstick_y;
|
||||
float pad_ltrigger;
|
||||
float pad_rtrigger;
|
||||
// Gamepad style input
|
||||
int pad_buttons; // bitfield
|
||||
int pad_last_buttons;
|
||||
int pad_buttons_down; // buttons just pressed this frame
|
||||
int pad_buttons_up; // buttons just pressed last frame
|
||||
float pad_lstick_x;
|
||||
float pad_lstick_y;
|
||||
float pad_rstick_x;
|
||||
float pad_rstick_y;
|
||||
float pad_ltrigger;
|
||||
float pad_rtrigger;
|
||||
|
||||
// Mouse/touch style input
|
||||
// There are up to 8 mice / fingers.
|
||||
volatile bool mouse_valid;
|
||||
// Mouse/touch style input
|
||||
// There are up to 8 mice / fingers.
|
||||
volatile bool mouse_valid;
|
||||
|
||||
int pointer_x[MAX_POINTERS];
|
||||
int pointer_y[MAX_POINTERS];
|
||||
bool pointer_down[MAX_POINTERS];
|
||||
int pointer_x[MAX_POINTERS];
|
||||
int pointer_y[MAX_POINTERS];
|
||||
bool pointer_down[MAX_POINTERS];
|
||||
|
||||
// Accelerometer
|
||||
bool accelerometer_valid;
|
||||
Vec3 acc;
|
||||
// Accelerometer
|
||||
bool accelerometer_valid;
|
||||
Vec3 acc;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(InputState);
|
||||
DISALLOW_COPY_AND_ASSIGN(InputState);
|
||||
};
|
||||
|
||||
inline void UpdateInputState(InputState *input) {
|
||||
input->pad_buttons_down = (input->pad_last_buttons ^ input->pad_buttons) & input->pad_buttons;
|
||||
input->pad_buttons_up = (input->pad_last_buttons ^ input->pad_buttons) & input->pad_last_buttons;
|
||||
input->pad_buttons_down = (input->pad_last_buttons ^ input->pad_buttons) & input->pad_buttons;
|
||||
input->pad_buttons_up = (input->pad_last_buttons ^ input->pad_buttons) & input->pad_last_buttons;
|
||||
}
|
||||
|
||||
inline void EndInputState(InputState *input) {
|
||||
input->pad_last_buttons = input->pad_buttons;
|
||||
input->pad_last_buttons = input->pad_buttons;
|
||||
}
|
||||
|
||||
+54
-54
@@ -7,109 +7,109 @@ JsonWriter::~JsonWriter() {
|
||||
}
|
||||
|
||||
void JsonWriter::begin() {
|
||||
str_ << "{";
|
||||
stack_.push_back(StackEntry(DICT));
|
||||
str_ << "{";
|
||||
stack_.push_back(StackEntry(DICT));
|
||||
}
|
||||
|
||||
void JsonWriter::end() {
|
||||
pop();
|
||||
str_ << "\n";
|
||||
pop();
|
||||
str_ << "\n";
|
||||
}
|
||||
|
||||
const char *JsonWriter::indent(int n) const {
|
||||
static const char * const whitespace = " ";
|
||||
return whitespace + (32 - n);
|
||||
static const char * const whitespace = " ";
|
||||
return whitespace + (32 - n);
|
||||
}
|
||||
|
||||
const char *JsonWriter::indent() const {
|
||||
int amount = (int)stack_.size() + 1;
|
||||
amount *= 2; // 2-space indent.
|
||||
return indent(amount);
|
||||
int amount = (int)stack_.size() + 1;
|
||||
amount *= 2; // 2-space indent.
|
||||
return indent(amount);
|
||||
}
|
||||
|
||||
const char *JsonWriter::arrayIndent() const {
|
||||
int amount = (int)stack_.size() + 1;
|
||||
amount *= 2; // 2-space indent.
|
||||
return stack_.back().first ? indent(amount) : "";
|
||||
int amount = (int)stack_.size() + 1;
|
||||
amount *= 2; // 2-space indent.
|
||||
return stack_.back().first ? indent(amount) : "";
|
||||
}
|
||||
|
||||
const char *JsonWriter::comma() const {
|
||||
if (stack_.back().first) {
|
||||
return "";
|
||||
} else {
|
||||
return ",";
|
||||
}
|
||||
if (stack_.back().first) {
|
||||
return "";
|
||||
} else {
|
||||
return ",";
|
||||
}
|
||||
}
|
||||
|
||||
const char *JsonWriter::arrayComma() const {
|
||||
if (stack_.back().first) {
|
||||
return "\n";
|
||||
} else {
|
||||
return ", ";
|
||||
}
|
||||
if (stack_.back().first) {
|
||||
return "\n";
|
||||
} else {
|
||||
return ", ";
|
||||
}
|
||||
}
|
||||
|
||||
void JsonWriter::pushDict(const char *name) {
|
||||
str_ << comma() << "\n" << indent() << "\"" << name << "\": {";
|
||||
stack_.push_back(StackEntry(DICT));
|
||||
str_ << comma() << "\n" << indent() << "\"" << name << "\": {";
|
||||
stack_.push_back(StackEntry(DICT));
|
||||
}
|
||||
|
||||
void JsonWriter::pushArray(const char *name) {
|
||||
str_ << comma() << "\n" << indent() << "\"" << name << "\": [";
|
||||
stack_.push_back(StackEntry(ARRAY));
|
||||
str_ << comma() << "\n" << indent() << "\"" << name << "\": [";
|
||||
stack_.push_back(StackEntry(ARRAY));
|
||||
}
|
||||
|
||||
void JsonWriter::writeBool(bool value) {
|
||||
str_ << arrayComma() << arrayIndent() << (value ? "true" : "false");
|
||||
stack_.back().first = false;
|
||||
str_ << arrayComma() << arrayIndent() << (value ? "true" : "false");
|
||||
stack_.back().first = false;
|
||||
}
|
||||
|
||||
void JsonWriter::writeBool(const char *name, bool value) {
|
||||
str_ << comma() << "\n" << indent() << "\"" << name << "\": " << (value ? "true" : "false");
|
||||
stack_.back().first = false;
|
||||
str_ << comma() << "\n" << indent() << "\"" << name << "\": " << (value ? "true" : "false");
|
||||
stack_.back().first = false;
|
||||
}
|
||||
|
||||
void JsonWriter::writeInt(int value) {
|
||||
str_ << arrayComma() << arrayIndent() << value;
|
||||
stack_.back().first = false;
|
||||
str_ << arrayComma() << arrayIndent() << value;
|
||||
stack_.back().first = false;
|
||||
}
|
||||
|
||||
void JsonWriter::writeInt(const char *name, int value) {
|
||||
str_ << comma() << "\n" << indent() << "\"" << name << "\": " << value;
|
||||
stack_.back().first = false;
|
||||
str_ << comma() << "\n" << indent() << "\"" << name << "\": " << value;
|
||||
stack_.back().first = false;
|
||||
}
|
||||
|
||||
void JsonWriter::writeFloat(double value) {
|
||||
str_ << arrayComma() << arrayIndent() << value;
|
||||
stack_.back().first = false;
|
||||
str_ << arrayComma() << arrayIndent() << value;
|
||||
stack_.back().first = false;
|
||||
}
|
||||
|
||||
void JsonWriter::writeFloat(const char *name, double value) {
|
||||
str_ << comma() << "\n" << indent() << "\"" << name << "\": " << value;
|
||||
stack_.back().first = false;
|
||||
str_ << comma() << "\n" << indent() << "\"" << name << "\": " << value;
|
||||
stack_.back().first = false;
|
||||
}
|
||||
|
||||
void JsonWriter::writeString(const char *value) {
|
||||
str_ << arrayComma() << arrayIndent() << "\"" << value << "\"";
|
||||
stack_.back().first = false;
|
||||
str_ << arrayComma() << arrayIndent() << "\"" << value << "\"";
|
||||
stack_.back().first = false;
|
||||
}
|
||||
|
||||
void JsonWriter::writeString(const char *name, const char *value) {
|
||||
str_ << comma() << "\n" << indent() << "\"" << name << "\": \"" << value << "\"";
|
||||
stack_.back().first = false;
|
||||
str_ << comma() << "\n" << indent() << "\"" << name << "\": \"" << value << "\"";
|
||||
stack_.back().first = false;
|
||||
}
|
||||
|
||||
void JsonWriter::pop() {
|
||||
BlockType type = stack_.back().type;
|
||||
stack_.pop_back();
|
||||
switch (type) {
|
||||
case ARRAY:
|
||||
str_ << "\n" << indent() << "]";
|
||||
break;
|
||||
case DICT:
|
||||
str_ << "\n" << indent() << "}";
|
||||
break;
|
||||
}
|
||||
if (stack_.size() > 0)
|
||||
stack_.back().first = false;
|
||||
BlockType type = stack_.back().type;
|
||||
stack_.pop_back();
|
||||
switch (type) {
|
||||
case ARRAY:
|
||||
str_ << "\n" << indent() << "]";
|
||||
break;
|
||||
case DICT:
|
||||
str_ << "\n" << indent() << "}";
|
||||
break;
|
||||
}
|
||||
if (stack_.size() > 0)
|
||||
stack_.back().first = false;
|
||||
}
|
||||
|
||||
+35
-35
@@ -18,43 +18,43 @@
|
||||
|
||||
class JsonWriter {
|
||||
public:
|
||||
JsonWriter();
|
||||
~JsonWriter();
|
||||
void begin();
|
||||
void end();
|
||||
void pushDict(const char *name);
|
||||
void pushArray(const char *name);
|
||||
void pop();
|
||||
void writeBool(bool value);
|
||||
void writeBool(const char *name, bool value);
|
||||
void writeInt(int value);
|
||||
void writeInt(const char *name, int value);
|
||||
void writeFloat(double value);
|
||||
void writeFloat(const char *name, double value);
|
||||
void writeString(const char *value);
|
||||
void writeString(const char *name, const char *value);
|
||||
JsonWriter();
|
||||
~JsonWriter();
|
||||
void begin();
|
||||
void end();
|
||||
void pushDict(const char *name);
|
||||
void pushArray(const char *name);
|
||||
void pop();
|
||||
void writeBool(bool value);
|
||||
void writeBool(const char *name, bool value);
|
||||
void writeInt(int value);
|
||||
void writeInt(const char *name, int value);
|
||||
void writeFloat(double value);
|
||||
void writeFloat(const char *name, double value);
|
||||
void writeString(const char *value);
|
||||
void writeString(const char *name, const char *value);
|
||||
|
||||
std::string str() const {
|
||||
return str_.str();
|
||||
}
|
||||
std::string str() const {
|
||||
return str_.str();
|
||||
}
|
||||
|
||||
private:
|
||||
const char *indent(int n) const;
|
||||
const char *comma() const;
|
||||
const char *arrayComma() const;
|
||||
const char *indent() const;
|
||||
const char *arrayIndent() const;
|
||||
enum BlockType {
|
||||
ARRAY,
|
||||
DICT,
|
||||
};
|
||||
struct StackEntry {
|
||||
StackEntry(BlockType t) : type(t), first(true) {}
|
||||
BlockType type;
|
||||
bool first;
|
||||
};
|
||||
std::vector<StackEntry> stack_;
|
||||
std::ostringstream str_;
|
||||
const char *indent(int n) const;
|
||||
const char *comma() const;
|
||||
const char *arrayComma() const;
|
||||
const char *indent() const;
|
||||
const char *arrayIndent() const;
|
||||
enum BlockType {
|
||||
ARRAY,
|
||||
DICT,
|
||||
};
|
||||
struct StackEntry {
|
||||
StackEntry(BlockType t) : type(t), first(true) {}
|
||||
BlockType type;
|
||||
bool first;
|
||||
};
|
||||
std::vector<StackEntry> stack_;
|
||||
std::ostringstream str_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(JsonWriter);
|
||||
DISALLOW_COPY_AND_ASSIGN(JsonWriter);
|
||||
};
|
||||
|
||||
+9
-9
@@ -5,18 +5,18 @@
|
||||
|
||||
template <class T>
|
||||
inline void delta(T *data, int length) {
|
||||
T prev = data[0];
|
||||
for (int i = 1; i < length; i++) {
|
||||
T temp = data[i] - prev;
|
||||
prev = data[i];
|
||||
data[i] = temp;
|
||||
}
|
||||
T prev = data[0];
|
||||
for (int i = 1; i < length; i++) {
|
||||
T temp = data[i] - prev;
|
||||
prev = data[i];
|
||||
data[i] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void dedelta(T *data, int length) {
|
||||
for (int i = 1; i < length; i++) {
|
||||
data[i] += data[i - 1];
|
||||
}
|
||||
for (int i = 1; i < length; i++) {
|
||||
data[i] += data[i - 1];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -15,7 +15,7 @@ struct AABB {
|
||||
bool Contains(const Vec3 &pt) const;
|
||||
bool IntersectRay(const Ray &ray, float &tnear, float &tfar) const;
|
||||
|
||||
// Doesn't currently work.
|
||||
// Doesn't currently work.
|
||||
bool IntersectRay2(const Ray &ray, float &tnear, float &tfar) const;
|
||||
|
||||
bool IntersectsTriangle(const Vec3& a_V0, const Vec3& a_V1, const Vec3& a_V2) const;
|
||||
@@ -36,5 +36,5 @@ struct AABB {
|
||||
return maxB - minB;
|
||||
}
|
||||
|
||||
bool BehindPlane(const Plane &plane) const;
|
||||
bool BehindPlane(const Plane &plane) const;
|
||||
};
|
||||
|
||||
+185
-185
@@ -10,271 +10,271 @@
|
||||
#undef near
|
||||
#endif
|
||||
|
||||
// See http://code.google.com/p/oolongengine/source/browse/trunk/Oolong+Engine2/Math/neonmath/neon_matrix_impl.cpp?spec=svn143&r=143 when we need speed
|
||||
// See http://code.google.com/p/oolongengine/source/browse/trunk/Oolong+Engine2/Math/neonmath/neon_matrix_impl.cpp?spec=svn143&r=143 when we need speed
|
||||
// no wait. http://code.google.com/p/math-neon/
|
||||
|
||||
void matrix_mul_4x4(Matrix4x4 &res, const Matrix4x4 &inA, const Matrix4x4 &inB) {
|
||||
res.xx = inA.xx*inB.xx + inA.xy*inB.yx + inA.xz*inB.zx + inA.xw*inB.wx;
|
||||
res.xy = inA.xx*inB.xy + inA.xy*inB.yy + inA.xz*inB.zy + inA.xw*inB.wy;
|
||||
res.xz = inA.xx*inB.xz + inA.xy*inB.yz + inA.xz*inB.zz + inA.xw*inB.wz;
|
||||
res.xw = inA.xx*inB.xw + inA.xy*inB.yw + inA.xz*inB.zw + inA.xw*inB.ww;
|
||||
res.xx = inA.xx*inB.xx + inA.xy*inB.yx + inA.xz*inB.zx + inA.xw*inB.wx;
|
||||
res.xy = inA.xx*inB.xy + inA.xy*inB.yy + inA.xz*inB.zy + inA.xw*inB.wy;
|
||||
res.xz = inA.xx*inB.xz + inA.xy*inB.yz + inA.xz*inB.zz + inA.xw*inB.wz;
|
||||
res.xw = inA.xx*inB.xw + inA.xy*inB.yw + inA.xz*inB.zw + inA.xw*inB.ww;
|
||||
|
||||
res.yx = inA.yx*inB.xx + inA.yy*inB.yx + inA.yz*inB.zx + inA.yw*inB.wx;
|
||||
res.yy = inA.yx*inB.xy + inA.yy*inB.yy + inA.yz*inB.zy + inA.yw*inB.wy;
|
||||
res.yz = inA.yx*inB.xz + inA.yy*inB.yz + inA.yz*inB.zz + inA.yw*inB.wz;
|
||||
res.yw = inA.yx*inB.xw + inA.yy*inB.yw + inA.yz*inB.zw + inA.yw*inB.ww;
|
||||
res.yx = inA.yx*inB.xx + inA.yy*inB.yx + inA.yz*inB.zx + inA.yw*inB.wx;
|
||||
res.yy = inA.yx*inB.xy + inA.yy*inB.yy + inA.yz*inB.zy + inA.yw*inB.wy;
|
||||
res.yz = inA.yx*inB.xz + inA.yy*inB.yz + inA.yz*inB.zz + inA.yw*inB.wz;
|
||||
res.yw = inA.yx*inB.xw + inA.yy*inB.yw + inA.yz*inB.zw + inA.yw*inB.ww;
|
||||
|
||||
res.zx = inA.zx*inB.xx + inA.zy*inB.yx + inA.zz*inB.zx + inA.zw*inB.wx;
|
||||
res.zy = inA.zx*inB.xy + inA.zy*inB.yy + inA.zz*inB.zy + inA.zw*inB.wy;
|
||||
res.zz = inA.zx*inB.xz + inA.zy*inB.yz + inA.zz*inB.zz + inA.zw*inB.wz;
|
||||
res.zw = inA.zx*inB.xw + inA.zy*inB.yw + inA.zz*inB.zw + inA.zw*inB.ww;
|
||||
res.zx = inA.zx*inB.xx + inA.zy*inB.yx + inA.zz*inB.zx + inA.zw*inB.wx;
|
||||
res.zy = inA.zx*inB.xy + inA.zy*inB.yy + inA.zz*inB.zy + inA.zw*inB.wy;
|
||||
res.zz = inA.zx*inB.xz + inA.zy*inB.yz + inA.zz*inB.zz + inA.zw*inB.wz;
|
||||
res.zw = inA.zx*inB.xw + inA.zy*inB.yw + inA.zz*inB.zw + inA.zw*inB.ww;
|
||||
|
||||
res.wx = inA.wx*inB.xx + inA.wy*inB.yx + inA.wz*inB.zx + inA.ww*inB.wx;
|
||||
res.wy = inA.wx*inB.xy + inA.wy*inB.yy + inA.wz*inB.zy + inA.ww*inB.wy;
|
||||
res.wz = inA.wx*inB.xz + inA.wy*inB.yz + inA.wz*inB.zz + inA.ww*inB.wz;
|
||||
res.ww = inA.wx*inB.xw + inA.wy*inB.yw + inA.wz*inB.zw + inA.ww*inB.ww;
|
||||
res.wx = inA.wx*inB.xx + inA.wy*inB.yx + inA.wz*inB.zx + inA.ww*inB.wx;
|
||||
res.wy = inA.wx*inB.xy + inA.wy*inB.yy + inA.wz*inB.zy + inA.ww*inB.wy;
|
||||
res.wz = inA.wx*inB.xz + inA.wy*inB.yz + inA.wz*inB.zz + inA.ww*inB.wz;
|
||||
res.ww = inA.wx*inB.xw + inA.wy*inB.yw + inA.wz*inB.zw + inA.ww*inB.ww;
|
||||
}
|
||||
|
||||
Matrix4x4 Matrix4x4::simpleInverse() const {
|
||||
Matrix4x4 out;
|
||||
out.xx = xx;
|
||||
out.xy = yx;
|
||||
out.xz = zx;
|
||||
Matrix4x4 out;
|
||||
out.xx = xx;
|
||||
out.xy = yx;
|
||||
out.xz = zx;
|
||||
|
||||
out.yx = xy;
|
||||
out.yy = yy;
|
||||
out.yz = zy;
|
||||
out.yx = xy;
|
||||
out.yy = yy;
|
||||
out.yz = zy;
|
||||
|
||||
out.zx = xz;
|
||||
out.zy = yz;
|
||||
out.zz = zz;
|
||||
out.zx = xz;
|
||||
out.zy = yz;
|
||||
out.zz = zz;
|
||||
|
||||
out.wx = -(xx * wx + xy * wy + xz * wz);
|
||||
out.wy = -(yx * wx + yy * wy + yz * wz);
|
||||
out.wz = -(zx * wx + zy * wy + zz * wz);
|
||||
out.wx = -(xx * wx + xy * wy + xz * wz);
|
||||
out.wy = -(yx * wx + yy * wy + yz * wz);
|
||||
out.wz = -(zx * wx + zy * wy + zz * wz);
|
||||
|
||||
out.xw = 0.0f;
|
||||
out.yw = 0.0f;
|
||||
out.zw = 0.0f;
|
||||
out.ww = 1.0f;
|
||||
out.xw = 0.0f;
|
||||
out.yw = 0.0f;
|
||||
out.zw = 0.0f;
|
||||
out.ww = 1.0f;
|
||||
|
||||
return out;
|
||||
return out;
|
||||
}
|
||||
Matrix4x4 Matrix4x4::transpose() const
|
||||
{
|
||||
Matrix4x4 out;
|
||||
out.xx = xx;out.xy = yx;out.xz = zx;out.xw = wx;
|
||||
out.yx = xy;out.yy = yy;out.yz = zy;out.yw = wy;
|
||||
out.zx = xz;out.zy = yz;out.zz = zz;out.zw = wz;
|
||||
out.wx = xw;out.wy = yw;out.wz = zw;out.ww = ww;
|
||||
return out;
|
||||
Matrix4x4 out;
|
||||
out.xx = xx;out.xy = yx;out.xz = zx;out.xw = wx;
|
||||
out.yx = xy;out.yy = yy;out.yz = zy;out.yw = wy;
|
||||
out.zx = xz;out.zy = yz;out.zz = zz;out.zw = wz;
|
||||
out.wx = xw;out.wy = yw;out.wz = zw;out.ww = ww;
|
||||
return out;
|
||||
}
|
||||
|
||||
Matrix4x4 Matrix4x4::operator * (const Matrix4x4 &other) const
|
||||
{
|
||||
Matrix4x4 temp;
|
||||
matrix_mul_4x4(temp, *this, other);
|
||||
return temp;
|
||||
Matrix4x4 temp;
|
||||
matrix_mul_4x4(temp, *this, other);
|
||||
return temp;
|
||||
}
|
||||
|
||||
Matrix4x4 Matrix4x4::inverse() const {
|
||||
Matrix4x4 temp;
|
||||
float dW = 1.0f / (xx*(yy*zz - yz*zy) - xy*(yx*zz - yz*zx) - xz*(yy*zx - yx*zy));
|
||||
Matrix4x4 temp;
|
||||
float dW = 1.0f / (xx*(yy*zz - yz*zy) - xy*(yx*zz - yz*zx) - xz*(yy*zx - yx*zy));
|
||||
|
||||
temp.xx = (yy*zz - yz*zy) * dW;
|
||||
temp.xy = (xz*zy - xy*zz) * dW;
|
||||
temp.xz = (xy*yz - xz*yy) * dW;
|
||||
temp.xw = xw;
|
||||
temp.xx = (yy*zz - yz*zy) * dW;
|
||||
temp.xy = (xz*zy - xy*zz) * dW;
|
||||
temp.xz = (xy*yz - xz*yy) * dW;
|
||||
temp.xw = xw;
|
||||
|
||||
temp.yx = (yz*zx - yx*zz) * dW;
|
||||
temp.yy = (xx*zz - xz*zx) * dW;
|
||||
temp.yz = (xz*yx - xx*zx) * dW;
|
||||
temp.yw = yw;
|
||||
temp.yx = (yz*zx - yx*zz) * dW;
|
||||
temp.yy = (xx*zz - xz*zx) * dW;
|
||||
temp.yz = (xz*yx - xx*zx) * dW;
|
||||
temp.yw = yw;
|
||||
|
||||
temp.zx = (yx*zy - yy*zx) * dW;
|
||||
temp.zy = (xy*zx - xx*zy) * dW;
|
||||
temp.zz = (xx*yy - xy*yx) * dW;
|
||||
temp.zw = zw;
|
||||
temp.zx = (yx*zy - yy*zx) * dW;
|
||||
temp.zy = (xy*zx - xx*zy) * dW;
|
||||
temp.zz = (xx*yy - xy*yx) * dW;
|
||||
temp.zw = zw;
|
||||
|
||||
temp.wx = (yy*(zx*wz - zz*wx) + yz*(zy*wx - zx*wy) - yx*(zy*wz - zz*wy)) * dW;
|
||||
temp.wy = (xx*(zy*wz - zz*wy) + xy*(zz*wx - zx*wz) + xz*(zx*wy - zy*wx)) * dW;
|
||||
temp.wz = (xy*(yx*wz - yz*wx) + xz*(yy*wx - yx*wy) - xx*(yy*wz - yz*wy)) * dW;
|
||||
temp.ww = ww;
|
||||
temp.wx = (yy*(zx*wz - zz*wx) + yz*(zy*wx - zx*wy) - yx*(zy*wz - zz*wy)) * dW;
|
||||
temp.wy = (xx*(zy*wz - zz*wy) + xy*(zz*wx - zx*wz) + xz*(zx*wy - zy*wx)) * dW;
|
||||
temp.wz = (xy*(yx*wz - yz*wx) + xz*(yy*wx - yx*wy) - xx*(yy*wz - yz*wy)) * dW;
|
||||
temp.ww = ww;
|
||||
|
||||
return temp;
|
||||
return temp;
|
||||
}
|
||||
|
||||
void Matrix4x4::setViewLookAt(const Vec3 &vFrom, const Vec3 &vAt, const Vec3 &vWorldUp) {
|
||||
Vec3 vView = vFrom - vAt; // OpenGL, sigh...
|
||||
vView.normalize();
|
||||
float DotProduct = vWorldUp * vView;
|
||||
Vec3 vUp = vWorldUp - vView * DotProduct;
|
||||
float Length = vUp.length();
|
||||
Vec3 vView = vFrom - vAt; // OpenGL, sigh...
|
||||
vView.normalize();
|
||||
float DotProduct = vWorldUp * vView;
|
||||
Vec3 vUp = vWorldUp - vView * DotProduct;
|
||||
float Length = vUp.length();
|
||||
|
||||
if (1e-6f > Length) {
|
||||
// EMERGENCY
|
||||
vUp = Vec3(0.0f, 1.0f, 0.0f) - vView * vView.y;
|
||||
// If we still have near-zero length, resort to a different axis.
|
||||
Length = vUp.length();
|
||||
if (1e-6f > Length)
|
||||
{
|
||||
vUp = Vec3(0.0f, 0.0f, 1.0f) - vView * vView.z;
|
||||
Length = vUp.length();
|
||||
if (1e-6f > Length)
|
||||
return;
|
||||
}
|
||||
}
|
||||
vUp.normalize();
|
||||
Vec3 vRight = vUp % vView;
|
||||
empty();
|
||||
if (1e-6f > Length) {
|
||||
// EMERGENCY
|
||||
vUp = Vec3(0.0f, 1.0f, 0.0f) - vView * vView.y;
|
||||
// If we still have near-zero length, resort to a different axis.
|
||||
Length = vUp.length();
|
||||
if (1e-6f > Length)
|
||||
{
|
||||
vUp = Vec3(0.0f, 0.0f, 1.0f) - vView * vView.z;
|
||||
Length = vUp.length();
|
||||
if (1e-6f > Length)
|
||||
return;
|
||||
}
|
||||
}
|
||||
vUp.normalize();
|
||||
Vec3 vRight = vUp % vView;
|
||||
empty();
|
||||
|
||||
xx = vRight.x; xy = vUp.x; xz=vView.x;
|
||||
yx = vRight.y; yy = vUp.y; yz=vView.y;
|
||||
zx = vRight.z; zy = vUp.z; zz=vView.z;
|
||||
xx = vRight.x; xy = vUp.x; xz=vView.x;
|
||||
yx = vRight.y; yy = vUp.y; yz=vView.y;
|
||||
zx = vRight.z; zy = vUp.z; zz=vView.z;
|
||||
|
||||
wx = -vFrom * vRight;
|
||||
wy = -vFrom * vUp;
|
||||
wz = -vFrom * vView;
|
||||
ww = 1.0f;
|
||||
wx = -vFrom * vRight;
|
||||
wy = -vFrom * vUp;
|
||||
wz = -vFrom * vView;
|
||||
ww = 1.0f;
|
||||
}
|
||||
|
||||
void Matrix4x4::setViewLookAtD3D(const Vec3 &vFrom, const Vec3 &vAt, const Vec3 &vWorldUp) {
|
||||
Vec3 vView = vAt - vFrom;
|
||||
vView.normalize();
|
||||
float DotProduct = vWorldUp * vView;
|
||||
Vec3 vUp = vWorldUp - vView * DotProduct;
|
||||
float Length = vUp.length();
|
||||
Vec3 vView = vAt - vFrom;
|
||||
vView.normalize();
|
||||
float DotProduct = vWorldUp * vView;
|
||||
Vec3 vUp = vWorldUp - vView * DotProduct;
|
||||
float Length = vUp.length();
|
||||
|
||||
if (1e-6f > Length) {
|
||||
vUp = Vec3(0.0f, 1.0f, 0.0f) - vView * vView.y;
|
||||
// If we still have near-zero length, resort to a different axis.
|
||||
Length = vUp.length();
|
||||
if (1e-6f > Length)
|
||||
{
|
||||
vUp = Vec3(0.0f, 0.0f, 1.0f) - vView * vView.z;
|
||||
Length = vUp.length();
|
||||
if (1e-6f > Length)
|
||||
return;
|
||||
}
|
||||
}
|
||||
vUp.normalize();
|
||||
Vec3 vRight = vUp % vView;
|
||||
empty();
|
||||
if (1e-6f > Length) {
|
||||
vUp = Vec3(0.0f, 1.0f, 0.0f) - vView * vView.y;
|
||||
// If we still have near-zero length, resort to a different axis.
|
||||
Length = vUp.length();
|
||||
if (1e-6f > Length)
|
||||
{
|
||||
vUp = Vec3(0.0f, 0.0f, 1.0f) - vView * vView.z;
|
||||
Length = vUp.length();
|
||||
if (1e-6f > Length)
|
||||
return;
|
||||
}
|
||||
}
|
||||
vUp.normalize();
|
||||
Vec3 vRight = vUp % vView;
|
||||
empty();
|
||||
|
||||
xx = vRight.x; xy = vUp.x; xz=vView.x;
|
||||
yx = vRight.y; yy = vUp.y; yz=vView.y;
|
||||
zx = vRight.z; zy = vUp.z; zz=vView.z;
|
||||
xx = vRight.x; xy = vUp.x; xz=vView.x;
|
||||
yx = vRight.y; yy = vUp.y; yz=vView.y;
|
||||
zx = vRight.z; zy = vUp.z; zz=vView.z;
|
||||
|
||||
wx = -vFrom * vRight;
|
||||
wy = -vFrom * vUp;
|
||||
wz = -vFrom * vView;
|
||||
ww = 1.0f;
|
||||
wx = -vFrom * vRight;
|
||||
wy = -vFrom * vUp;
|
||||
wz = -vFrom * vView;
|
||||
ww = 1.0f;
|
||||
}
|
||||
|
||||
|
||||
void Matrix4x4::setViewFrame(const Vec3 &pos, const Vec3 &vRight, const Vec3 &vView, const Vec3 &vUp) {
|
||||
xx = vRight.x; xy = vUp.x; xz=vView.x; xw = 0.0f;
|
||||
yx = vRight.y; yy = vUp.y; yz=vView.y; yw = 0.0f;
|
||||
zx = vRight.z; zy = vUp.z; zz=vView.z; zw = 0.0f;
|
||||
xx = vRight.x; xy = vUp.x; xz=vView.x; xw = 0.0f;
|
||||
yx = vRight.y; yy = vUp.y; yz=vView.y; yw = 0.0f;
|
||||
zx = vRight.z; zy = vUp.z; zz=vView.z; zw = 0.0f;
|
||||
|
||||
wx = -pos * vRight;
|
||||
wy = -pos * vUp;
|
||||
wz = -pos * vView;
|
||||
ww = 1.0f;
|
||||
wx = -pos * vRight;
|
||||
wy = -pos * vUp;
|
||||
wz = -pos * vView;
|
||||
ww = 1.0f;
|
||||
}
|
||||
|
||||
//YXZ euler angles
|
||||
void Matrix4x4::setRotation(float x,float y, float z)
|
||||
{
|
||||
setRotationY(y);
|
||||
Matrix4x4 temp;
|
||||
temp.setRotationX(x);
|
||||
*this *= temp;
|
||||
temp.setRotationZ(z);
|
||||
*this *= temp;
|
||||
setRotationY(y);
|
||||
Matrix4x4 temp;
|
||||
temp.setRotationX(x);
|
||||
*this *= temp;
|
||||
temp.setRotationZ(z);
|
||||
*this *= temp;
|
||||
}
|
||||
|
||||
void Matrix4x4::setProjection(float near, float far, float fov_horiz, float aspect) {
|
||||
// Now OpenGL style.
|
||||
empty();
|
||||
// Now OpenGL style.
|
||||
empty();
|
||||
|
||||
float xFac = tanf(fov_horiz * 3.14f/360);
|
||||
float yFac = xFac * aspect;
|
||||
xx = 1.0f / xFac;
|
||||
yy = 1.0f / yFac;
|
||||
zz = -(far+near)/(far-near);
|
||||
zw = -1.0f;
|
||||
wz = -(2*far*near)/(far-near);
|
||||
float xFac = tanf(fov_horiz * 3.14f/360);
|
||||
float yFac = xFac * aspect;
|
||||
xx = 1.0f / xFac;
|
||||
yy = 1.0f / yFac;
|
||||
zz = -(far+near)/(far-near);
|
||||
zw = -1.0f;
|
||||
wz = -(2*far*near)/(far-near);
|
||||
}
|
||||
|
||||
void Matrix4x4::setProjectionD3D(float near_plane, float far_plane, float fov_horiz, float aspect) {
|
||||
empty();
|
||||
float Q, f;
|
||||
empty();
|
||||
float Q, f;
|
||||
|
||||
f = fov_horiz*0.5f;
|
||||
Q = far_plane / (far_plane - near_plane);
|
||||
f = fov_horiz*0.5f;
|
||||
Q = far_plane / (far_plane - near_plane);
|
||||
|
||||
xx = (float)(1.0f / tanf(f));;
|
||||
yy = (float)(1.0f / tanf(f*aspect));
|
||||
zz = Q;
|
||||
wz = -Q * near_plane;
|
||||
zw = 1.0f;
|
||||
xx = (float)(1.0f / tanf(f));;
|
||||
yy = (float)(1.0f / tanf(f*aspect));
|
||||
zz = Q;
|
||||
wz = -Q * near_plane;
|
||||
zw = 1.0f;
|
||||
}
|
||||
|
||||
void Matrix4x4::setOrtho(float left, float right, float bottom, float top, float near, float far) {
|
||||
setIdentity();
|
||||
xx = 2.0f / (right - left);
|
||||
yy = 2.0f / (top - bottom);
|
||||
zz = 2.0f / (far - near);
|
||||
wx = -(right + left) / (right - left);
|
||||
wy = -(top + bottom) / (top - bottom);
|
||||
wz = -(far + near) / (far - near);
|
||||
setIdentity();
|
||||
xx = 2.0f / (right - left);
|
||||
yy = 2.0f / (top - bottom);
|
||||
zz = 2.0f / (far - near);
|
||||
wx = -(right + left) / (right - left);
|
||||
wy = -(top + bottom) / (top - bottom);
|
||||
wz = -(far + near) / (far - near);
|
||||
}
|
||||
|
||||
// This is a D3D style matrix.
|
||||
void Matrix4x4::setProjectionInf(const float near_plane, const float fov_horiz, const float aspect) {
|
||||
empty();
|
||||
float f = fov_horiz*0.5f;
|
||||
xx = 1.0f / tanf(f);
|
||||
yy = 1.0f / tanf(f*aspect);
|
||||
zz = 1;
|
||||
wz = -near_plane;
|
||||
zw = 1.0f;
|
||||
empty();
|
||||
float f = fov_horiz*0.5f;
|
||||
xx = 1.0f / tanf(f);
|
||||
yy = 1.0f / tanf(f*aspect);
|
||||
zz = 1;
|
||||
wz = -near_plane;
|
||||
zw = 1.0f;
|
||||
}
|
||||
|
||||
void Matrix4x4::setRotationAxisAngle(const Vec3 &axis, float angle) {
|
||||
Quaternion quat;
|
||||
quat.setRotation(axis, angle);
|
||||
quat.toMatrix(this);
|
||||
Quaternion quat;
|
||||
quat.setRotation(axis, angle);
|
||||
quat.toMatrix(this);
|
||||
}
|
||||
|
||||
// from a (Position, Rotation, Scale) vec3 quat vec3 tuple
|
||||
Matrix4x4 Matrix4x4::fromPRS(const Vec3 &positionv, const Quaternion &rotv, const Vec3 &scalev) {
|
||||
Matrix4x4 newM;
|
||||
newM.setIdentity();
|
||||
Matrix4x4 rot, scale;
|
||||
rotv.toMatrix(&rot);
|
||||
scale.setScaling(scalev);
|
||||
newM = rot * scale;
|
||||
newM.wx = positionv.x;
|
||||
newM.wy = positionv.y;
|
||||
newM.wz = positionv.z;
|
||||
return newM;
|
||||
Matrix4x4 newM;
|
||||
newM.setIdentity();
|
||||
Matrix4x4 rot, scale;
|
||||
rotv.toMatrix(&rot);
|
||||
scale.setScaling(scalev);
|
||||
newM = rot * scale;
|
||||
newM.wx = positionv.x;
|
||||
newM.wy = positionv.y;
|
||||
newM.wz = positionv.z;
|
||||
return newM;
|
||||
}
|
||||
#if _MSC_VER
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
void Matrix4x4::toText(char *buffer, int len) const {
|
||||
snprintf(buffer, len, "%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n",
|
||||
xx,xy,xz,xw,
|
||||
yx,yy,yz,yw,
|
||||
zx,zy,zz,zw,
|
||||
wx,wy,wz,ww);
|
||||
buffer[len - 1] = '\0';
|
||||
snprintf(buffer, len, "%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n",
|
||||
xx,xy,xz,xw,
|
||||
yx,yy,yz,yw,
|
||||
zx,zy,zz,zw,
|
||||
wx,wy,wz,ww);
|
||||
buffer[len - 1] = '\0';
|
||||
}
|
||||
|
||||
void Matrix4x4::print() const {
|
||||
char buffer[256];
|
||||
toText(buffer, 256);
|
||||
puts(buffer);
|
||||
char buffer[256];
|
||||
toText(buffer, 256);
|
||||
puts(buffer);
|
||||
}
|
||||
|
||||
+119
-119
@@ -7,135 +7,135 @@ class Quaternion;
|
||||
|
||||
class Matrix4x4 {
|
||||
public:
|
||||
float xx, xy, xz, xw;
|
||||
float yx, yy, yz, yw;
|
||||
float zx, zy, zz, zw;
|
||||
float wx, wy, wz, ww;
|
||||
float xx, xy, xz, xw;
|
||||
float yx, yy, yz, yw;
|
||||
float zx, zy, zz, zw;
|
||||
float wx, wy, wz, ww;
|
||||
|
||||
const Vec3 right() const {return Vec3(xx, xy, xz);}
|
||||
const Vec3 up() const {return Vec3(yx, yy, yz);}
|
||||
const Vec3 front() const {return Vec3(zx, zy, zz);}
|
||||
const Vec3 move() const {return Vec3(wx, wy, wz);}
|
||||
const Vec3 right() const {return Vec3(xx, xy, xz);}
|
||||
const Vec3 up() const {return Vec3(yx, yy, yz);}
|
||||
const Vec3 front() const {return Vec3(zx, zy, zz);}
|
||||
const Vec3 move() const {return Vec3(wx, wy, wz);}
|
||||
|
||||
void setRight(const Vec3 &v) {
|
||||
xx = v.x; xy = v.y; xz = v.z;
|
||||
}
|
||||
void setUp(const Vec3 &v) {
|
||||
yx = v.x; yy = v.y; yz = v.z;
|
||||
}
|
||||
void setFront(const Vec3 &v) {
|
||||
zx = v.x; zy = v.y; zz = v.z;
|
||||
}
|
||||
void setMove(const Vec3 &v) {
|
||||
wx = v.x; wy = v.y; wz = v.z;
|
||||
}
|
||||
void setRight(const Vec3 &v) {
|
||||
xx = v.x; xy = v.y; xz = v.z;
|
||||
}
|
||||
void setUp(const Vec3 &v) {
|
||||
yx = v.x; yy = v.y; yz = v.z;
|
||||
}
|
||||
void setFront(const Vec3 &v) {
|
||||
zx = v.x; zy = v.y; zz = v.z;
|
||||
}
|
||||
void setMove(const Vec3 &v) {
|
||||
wx = v.x; wy = v.y; wz = v.z;
|
||||
}
|
||||
|
||||
|
||||
const float &operator[](int i) const {
|
||||
return *(((const float *)this) + i);
|
||||
}
|
||||
float &operator[](int i) {
|
||||
return *(((float *)this) + i);
|
||||
}
|
||||
Matrix4x4 operator * (const Matrix4x4 &other) const ;
|
||||
void operator *= (const Matrix4x4 &other) {
|
||||
*this = *this * other;
|
||||
}
|
||||
const float *getReadPtr() const {
|
||||
return (const float *)this;
|
||||
}
|
||||
void empty() {
|
||||
memset(this, 0, 16 * sizeof(float));
|
||||
}
|
||||
void setScaling(const float f) {
|
||||
empty();
|
||||
xx=yy=zz=f; ww=1.0f;
|
||||
}
|
||||
void setScaling(const Vec3 f) {
|
||||
empty();
|
||||
xx=f.x;
|
||||
yy=f.y;
|
||||
zz=f.z;
|
||||
ww=1.0f;
|
||||
}
|
||||
const float &operator[](int i) const {
|
||||
return *(((const float *)this) + i);
|
||||
}
|
||||
float &operator[](int i) {
|
||||
return *(((float *)this) + i);
|
||||
}
|
||||
Matrix4x4 operator * (const Matrix4x4 &other) const ;
|
||||
void operator *= (const Matrix4x4 &other) {
|
||||
*this = *this * other;
|
||||
}
|
||||
const float *getReadPtr() const {
|
||||
return (const float *)this;
|
||||
}
|
||||
void empty() {
|
||||
memset(this, 0, 16 * sizeof(float));
|
||||
}
|
||||
void setScaling(const float f) {
|
||||
empty();
|
||||
xx=yy=zz=f; ww=1.0f;
|
||||
}
|
||||
void setScaling(const Vec3 f) {
|
||||
empty();
|
||||
xx=f.x;
|
||||
yy=f.y;
|
||||
zz=f.z;
|
||||
ww=1.0f;
|
||||
}
|
||||
|
||||
void setIdentity() {
|
||||
setScaling(1.0f);
|
||||
}
|
||||
void setTranslation(const Vec3 &trans) {
|
||||
setIdentity();
|
||||
wx = trans.x;
|
||||
wy = trans.y;
|
||||
wz = trans.z;
|
||||
}
|
||||
Matrix4x4 inverse() const;
|
||||
Matrix4x4 simpleInverse() const;
|
||||
Matrix4x4 transpose() const;
|
||||
void setIdentity() {
|
||||
setScaling(1.0f);
|
||||
}
|
||||
void setTranslation(const Vec3 &trans) {
|
||||
setIdentity();
|
||||
wx = trans.x;
|
||||
wy = trans.y;
|
||||
wz = trans.z;
|
||||
}
|
||||
Matrix4x4 inverse() const;
|
||||
Matrix4x4 simpleInverse() const;
|
||||
Matrix4x4 transpose() const;
|
||||
|
||||
void setRotationX(const float a) {
|
||||
empty();
|
||||
float c=cosf(a);
|
||||
float s=sinf(a);
|
||||
xx = 1.0f;
|
||||
yy = c; yz = s;
|
||||
zy = -s; zz = c;
|
||||
ww = 1.0f;
|
||||
}
|
||||
void setRotationY(const float a) {
|
||||
empty();
|
||||
float c=cosf(a);
|
||||
float s=sinf(a);
|
||||
xx = c; xz = -s;
|
||||
yy = 1.0f;
|
||||
zx = s; zz = c ;
|
||||
ww = 1.0f;
|
||||
}
|
||||
void setRotationZ(const float a) {
|
||||
empty();
|
||||
float c=cosf(a);
|
||||
float s=sinf(a);
|
||||
xx = c; xy = s;
|
||||
yx = -s; yy = c;
|
||||
zz = 1.0f;
|
||||
ww = 1.0f;
|
||||
}
|
||||
void setRotationAxisAngle(const Vec3 &axis, float angle);
|
||||
void setRotationX(const float a) {
|
||||
empty();
|
||||
float c=cosf(a);
|
||||
float s=sinf(a);
|
||||
xx = 1.0f;
|
||||
yy = c; yz = s;
|
||||
zy = -s; zz = c;
|
||||
ww = 1.0f;
|
||||
}
|
||||
void setRotationY(const float a) {
|
||||
empty();
|
||||
float c=cosf(a);
|
||||
float s=sinf(a);
|
||||
xx = c; xz = -s;
|
||||
yy = 1.0f;
|
||||
zx = s; zz = c ;
|
||||
ww = 1.0f;
|
||||
}
|
||||
void setRotationZ(const float a) {
|
||||
empty();
|
||||
float c=cosf(a);
|
||||
float s=sinf(a);
|
||||
xx = c; xy = s;
|
||||
yx = -s; yy = c;
|
||||
zz = 1.0f;
|
||||
ww = 1.0f;
|
||||
}
|
||||
void setRotationAxisAngle(const Vec3 &axis, float angle);
|
||||
|
||||
|
||||
void setRotation(float x,float y, float z);
|
||||
void setProjection(float near_plane, float far_plane, float fov_horiz, float aspect = 0.75f);
|
||||
void setProjectionD3D(float near_plane, float far_plane, float fov_horiz, float aspect = 0.75f);
|
||||
void setProjectionInf(float near_plane, float fov_horiz, float aspect = 0.75f);
|
||||
void setOrtho(float left, float right, float bottom, float top, float near, float far);
|
||||
void setShadow(float Lx, float Ly, float Lz, float Lw) {
|
||||
float Pa=0;
|
||||
float Pb=1;
|
||||
float Pc=0;
|
||||
float Pd=0;
|
||||
//P = normalize(Plane);
|
||||
float d = (Pa*Lx + Pb*Ly + Pc*Lz + Pd*Lw);
|
||||
void setRotation(float x,float y, float z);
|
||||
void setProjection(float near_plane, float far_plane, float fov_horiz, float aspect = 0.75f);
|
||||
void setProjectionD3D(float near_plane, float far_plane, float fov_horiz, float aspect = 0.75f);
|
||||
void setProjectionInf(float near_plane, float fov_horiz, float aspect = 0.75f);
|
||||
void setOrtho(float left, float right, float bottom, float top, float near, float far);
|
||||
void setShadow(float Lx, float Ly, float Lz, float Lw) {
|
||||
float Pa=0;
|
||||
float Pb=1;
|
||||
float Pc=0;
|
||||
float Pd=0;
|
||||
//P = normalize(Plane);
|
||||
float d = (Pa*Lx + Pb*Ly + Pc*Lz + Pd*Lw);
|
||||
|
||||
xx=Pa * Lx + d; xy=Pa * Ly; xz=Pa * Lz; xw=Pa * Lw;
|
||||
yx=Pb * Lx; yy=Pb * Ly + d; yz=Pb * Lz; yw=Pb * Lw;
|
||||
zx=Pc * Lx; zy=Pc * Ly; zz=Pc * Lz + d; zw=Pc * Lw;
|
||||
wx=Pd * Lx; wy=Pd * Ly; wz=Pd * Lz; ww=Pd * Lw + d;
|
||||
}
|
||||
xx=Pa * Lx + d; xy=Pa * Ly; xz=Pa * Lz; xw=Pa * Lw;
|
||||
yx=Pb * Lx; yy=Pb * Ly + d; yz=Pb * Lz; yw=Pb * Lw;
|
||||
zx=Pc * Lx; zy=Pc * Ly; zz=Pc * Lz + d; zw=Pc * Lw;
|
||||
wx=Pd * Lx; wy=Pd * Ly; wz=Pd * Lz; ww=Pd * Lw + d;
|
||||
}
|
||||
|
||||
void setViewLookAt(const Vec3 &from, const Vec3 &at, const Vec3 &worldup);
|
||||
void setViewLookAtD3D(const Vec3 &from, const Vec3 &at, const Vec3 &worldup);
|
||||
void setViewFrame(const Vec3 &pos, const Vec3 &right, const Vec3 &forward, const Vec3 &up);
|
||||
void stabilizeOrtho() {
|
||||
/*
|
||||
front().normalize();
|
||||
right().normalize();
|
||||
up() = front() % right();
|
||||
right() = up() % front();
|
||||
*/
|
||||
}
|
||||
void toText(char *buffer, int len) const;
|
||||
void print() const;
|
||||
static Matrix4x4 fromPRS(const Vec3 &position, const Quaternion &normal, const Vec3 &scale);
|
||||
void setViewLookAt(const Vec3 &from, const Vec3 &at, const Vec3 &worldup);
|
||||
void setViewLookAtD3D(const Vec3 &from, const Vec3 &at, const Vec3 &worldup);
|
||||
void setViewFrame(const Vec3 &pos, const Vec3 &right, const Vec3 &forward, const Vec3 &up);
|
||||
void stabilizeOrtho() {
|
||||
/*
|
||||
front().normalize();
|
||||
right().normalize();
|
||||
up() = front() % right();
|
||||
right() = up() % front();
|
||||
*/
|
||||
}
|
||||
void toText(char *buffer, int len) const;
|
||||
void print() const;
|
||||
static Matrix4x4 fromPRS(const Vec3 &position, const Quaternion &normal, const Vec3 &scale);
|
||||
};
|
||||
|
||||
#endif // _MATH_LIN_MATRIX4X4_H
|
||||
#endif // _MATH_LIN_MATRIX4X4_H
|
||||
|
||||
|
||||
+4
-4
@@ -3,8 +3,8 @@
|
||||
|
||||
|
||||
void Plane::TransformByIT(const Matrix4x4 &m, Plane *out) {
|
||||
out->x = x * m.xx + y * m.yx + z * m.zx + d * m.wx;
|
||||
out->y = x * m.xy + y * m.yy + z * m.zy + d * m.wy;
|
||||
out->z = x * m.xz + y * m.yz + z * m.zz + d * m.wz;
|
||||
out->d = x * m.xw + y * m.yw + z * m.zw + d * m.ww;
|
||||
out->x = x * m.xx + y * m.yx + z * m.zx + d * m.wx;
|
||||
out->y = x * m.xy + y * m.yy + z * m.zy + d * m.wy;
|
||||
out->z = x * m.xz + y * m.yz + z * m.zz + d * m.wz;
|
||||
out->d = x * m.xw + y * m.yw + z * m.zw + d * m.ww;
|
||||
}
|
||||
|
||||
+22
-22
@@ -6,32 +6,32 @@
|
||||
class Matrix4x4;
|
||||
|
||||
class Plane {
|
||||
public:
|
||||
float x, y, z, d;
|
||||
Plane() {}
|
||||
Plane(float x_, float y_, float z_, float d_)
|
||||
: x(x_), y(y_), z(z_), d(d_) { }
|
||||
~Plane() {}
|
||||
public:
|
||||
float x, y, z, d;
|
||||
Plane() {}
|
||||
Plane(float x_, float y_, float z_, float d_)
|
||||
: x(x_), y(y_), z(z_), d(d_) { }
|
||||
~Plane() {}
|
||||
|
||||
float Distance(const Vec3 &v) const {
|
||||
return x * v.x + y * v.y + z * v.z + d;
|
||||
}
|
||||
float Distance(const Vec3 &v) const {
|
||||
return x * v.x + y * v.y + z * v.z + d;
|
||||
}
|
||||
|
||||
float Distance(float px, float py, float pz) const {
|
||||
return x * px + y * py + z * pz + d;
|
||||
}
|
||||
float Distance(float px, float py, float pz) const {
|
||||
return x * px + y * py + z * pz + d;
|
||||
}
|
||||
|
||||
void Normalize() {
|
||||
float inv_length = sqrtf(x * x + y * y + z * z);
|
||||
x *= inv_length;
|
||||
y *= inv_length;
|
||||
z *= inv_length;
|
||||
d *= inv_length;
|
||||
}
|
||||
void Normalize() {
|
||||
float inv_length = sqrtf(x * x + y * y + z * z);
|
||||
x *= inv_length;
|
||||
y *= inv_length;
|
||||
z *= inv_length;
|
||||
d *= inv_length;
|
||||
}
|
||||
|
||||
// Matrix is the inverse transpose of the wanted transform.
|
||||
// out cannot be equal to this.
|
||||
void TransformByIT(const Matrix4x4 &matrix, Plane *out);
|
||||
// Matrix is the inverse transpose of the wanted transform.
|
||||
// out cannot be equal to this.
|
||||
void TransformByIT(const Matrix4x4 &matrix, Plane *out);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
+88
-88
@@ -2,124 +2,124 @@
|
||||
#include "math/lin/matrix4x4.h"
|
||||
|
||||
void Quaternion::toMatrix(Matrix4x4 *out) const {
|
||||
Matrix4x4 temp;
|
||||
temp.setIdentity();
|
||||
float ww, xx, yy, zz, wx, wy, wz, xy, xz, yz;
|
||||
ww = w*w; xx = x*x; yy = y*y; zz = z*z;
|
||||
wx = w*x*2; wy = w*y*2; wz = w*z*2;
|
||||
xy = x*y*2; xz = x*z*2; yz = y*z*2;
|
||||
Matrix4x4 temp;
|
||||
temp.setIdentity();
|
||||
float ww, xx, yy, zz, wx, wy, wz, xy, xz, yz;
|
||||
ww = w*w; xx = x*x; yy = y*y; zz = z*z;
|
||||
wx = w*x*2; wy = w*y*2; wz = w*z*2;
|
||||
xy = x*y*2; xz = x*z*2; yz = y*z*2;
|
||||
|
||||
temp.xx = ww + xx - yy - zz;
|
||||
temp.xy = xy + wz;
|
||||
temp.xz = xz - wy;
|
||||
temp.xx = ww + xx - yy - zz;
|
||||
temp.xy = xy + wz;
|
||||
temp.xz = xz - wy;
|
||||
|
||||
temp.yx = xy - wz;
|
||||
temp.yy = ww - xx + yy - zz;
|
||||
temp.yz = yz + wx;
|
||||
temp.yx = xy - wz;
|
||||
temp.yy = ww - xx + yy - zz;
|
||||
temp.yz = yz + wx;
|
||||
|
||||
temp.zx = xz + wy;
|
||||
temp.zy = yz - wx;
|
||||
temp.zz = ww - xx - yy + zz;
|
||||
temp.zx = xz + wy;
|
||||
temp.zy = yz - wx;
|
||||
temp.zz = ww - xx - yy + zz;
|
||||
|
||||
*out = temp;
|
||||
*out = temp;
|
||||
}
|
||||
|
||||
Quaternion Quaternion::fromMatrix(Matrix4x4 &m)
|
||||
{
|
||||
// Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes
|
||||
// article "Quaternion Calculus and Fast Animation".
|
||||
Quaternion q(0,0,0,1);
|
||||
/*
|
||||
float fTrace = m[0][0] + m[1][1] + m[2][2];
|
||||
float fRoot;
|
||||
// Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes
|
||||
// article "Quaternion Calculus and Fast Animation".
|
||||
Quaternion q(0,0,0,1);
|
||||
/*
|
||||
float fTrace = m[0][0] + m[1][1] + m[2][2];
|
||||
float fRoot;
|
||||
|
||||
if( fTrace > 0.0 )
|
||||
{
|
||||
fRoot = sqrtf( fTrace + 1.0f );
|
||||
if( fTrace > 0.0 )
|
||||
{
|
||||
fRoot = sqrtf( fTrace + 1.0f );
|
||||
|
||||
q.w = 0.5f * fRoot;
|
||||
q.w = 0.5f * fRoot;
|
||||
|
||||
fRoot = 0.5f / fRoot;
|
||||
fRoot = 0.5f / fRoot;
|
||||
|
||||
q.x = ( m[2][1] - m[1][2] ) * fRoot;
|
||||
q.y = ( m[0][2] - m[2][0] ) * fRoot;
|
||||
q.z = ( m[1][0] - m[0][1] ) * fRoot;
|
||||
}
|
||||
else
|
||||
{
|
||||
int iNext[3] = { 1, 2, 0 };
|
||||
q.x = ( m[2][1] - m[1][2] ) * fRoot;
|
||||
q.y = ( m[0][2] - m[2][0] ) * fRoot;
|
||||
q.z = ( m[1][0] - m[0][1] ) * fRoot;
|
||||
}
|
||||
else
|
||||
{
|
||||
int iNext[3] = { 1, 2, 0 };
|
||||
|
||||
int i = 0;
|
||||
if( m[1][1] > m[0][0] )
|
||||
i = 1;
|
||||
int i = 0;
|
||||
if( m[1][1] > m[0][0] )
|
||||
i = 1;
|
||||
|
||||
if( m[2][2] > m[i][i] )
|
||||
i = 2;
|
||||
if( m[2][2] > m[i][i] )
|
||||
i = 2;
|
||||
|
||||
int j = iNext[i];
|
||||
int k = iNext[j];
|
||||
int j = iNext[i];
|
||||
int k = iNext[j];
|
||||
|
||||
fRoot = sqrtf( m[i][i] - m[j][j] - m[k][k] + 1.0f );
|
||||
fRoot = sqrtf( m[i][i] - m[j][j] - m[k][k] + 1.0f );
|
||||
|
||||
float *apfQuat = &q.x;
|
||||
float *apfQuat = &q.x;
|
||||
|
||||
apfQuat[i] = 0.5f * fRoot;
|
||||
apfQuat[i] = 0.5f * fRoot;
|
||||
|
||||
fRoot = 0.5f / fRoot;
|
||||
fRoot = 0.5f / fRoot;
|
||||
|
||||
q.w = ( m[k][j] - m[j][k] ) * fRoot;
|
||||
q.w = ( m[k][j] - m[j][k] ) * fRoot;
|
||||
|
||||
apfQuat[j] = ( m[j][i] + m[i][j] ) * fRoot;
|
||||
apfQuat[k] = ( m[k][i] + m[i][k] ) * fRoot;
|
||||
}
|
||||
q.normalize(); */
|
||||
return q;
|
||||
apfQuat[j] = ( m[j][i] + m[i][j] ) * fRoot;
|
||||
apfQuat[k] = ( m[k][i] + m[i][k] ) * fRoot;
|
||||
}
|
||||
q.normalize(); */
|
||||
return q;
|
||||
};
|
||||
|
||||
// TODO: Allegedly, lerp + normalize can achieve almost as good results.
|
||||
Quaternion Quaternion::slerp(const Quaternion &to, const float a) const {
|
||||
Quaternion to2;
|
||||
float angle, cos_angle, scale_from, scale_to, sin_angle;
|
||||
Quaternion to2;
|
||||
float angle, cos_angle, scale_from, scale_to, sin_angle;
|
||||
|
||||
cos_angle = (x * to.x) + (y * to.y) + (z * to.z) + (w * to.w); //4D dot product
|
||||
cos_angle = (x * to.x) + (y * to.y) + (z * to.z) + (w * to.w); //4D dot product
|
||||
|
||||
if (cos_angle < 0.0f)
|
||||
{
|
||||
cos_angle = -cos_angle;
|
||||
to2.w = -to.w; to2.x = -to.x; to2.y = -to.y; to2.z = -to.z;
|
||||
}
|
||||
else
|
||||
{
|
||||
to2 = to;
|
||||
}
|
||||
if (cos_angle < 0.0f)
|
||||
{
|
||||
cos_angle = -cos_angle;
|
||||
to2.w = -to.w; to2.x = -to.x; to2.y = -to.y; to2.z = -to.z;
|
||||
}
|
||||
else
|
||||
{
|
||||
to2 = to;
|
||||
}
|
||||
|
||||
if ((1.0f - fabsf(cos_angle)) > 0.00001f)
|
||||
{
|
||||
/* spherical linear interpolation (SLERP) */
|
||||
angle = acosf(cos_angle);
|
||||
sin_angle = sinf(angle);
|
||||
scale_from = sinf((1.0f - a) * angle) / sin_angle;
|
||||
scale_to = sinf(a * angle) / sin_angle;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* to prevent divide-by-zero, resort to linear interpolation */
|
||||
// This is okay in 99% of cases anyway, maybe should be the default?
|
||||
scale_from = 1.0f - a;
|
||||
scale_to = a;
|
||||
}
|
||||
if ((1.0f - fabsf(cos_angle)) > 0.00001f)
|
||||
{
|
||||
/* spherical linear interpolation (SLERP) */
|
||||
angle = acosf(cos_angle);
|
||||
sin_angle = sinf(angle);
|
||||
scale_from = sinf((1.0f - a) * angle) / sin_angle;
|
||||
scale_to = sinf(a * angle) / sin_angle;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* to prevent divide-by-zero, resort to linear interpolation */
|
||||
// This is okay in 99% of cases anyway, maybe should be the default?
|
||||
scale_from = 1.0f - a;
|
||||
scale_to = a;
|
||||
}
|
||||
|
||||
return Quaternion(
|
||||
scale_from*x + scale_to*to2.x,
|
||||
scale_from*y + scale_to*to2.y,
|
||||
scale_from*z + scale_to*to2.z,
|
||||
scale_from*w + scale_to*to2.w
|
||||
);
|
||||
return Quaternion(
|
||||
scale_from*x + scale_to*to2.x,
|
||||
scale_from*y + scale_to*to2.y,
|
||||
scale_from*z + scale_to*to2.z,
|
||||
scale_from*w + scale_to*to2.w
|
||||
);
|
||||
}
|
||||
|
||||
Quaternion Quaternion::multiply(const Quaternion &q) const {
|
||||
return Quaternion((w * q.x) + (x * q.w) + (y * q.z) - (z * q.y),
|
||||
(w * q.y) + (y * q.w) + (z * q.x) - (x * q.z),
|
||||
(w * q.z) + (z * q.w) + (x * q.y) - (y * q.x),
|
||||
(w * q.w) - (x * q.x) - (y * q.y) - (z * q.z));
|
||||
return Quaternion((w * q.x) + (x * q.w) + (y * q.z) - (z * q.y),
|
||||
(w * q.y) + (y * q.w) + (z * q.x) - (x * q.z),
|
||||
(w * q.z) + (z * q.w) + (x * q.y) - (y * q.x),
|
||||
(w * q.w) - (x * q.x) - (y * q.y) - (z * q.z));
|
||||
}
|
||||
|
||||
+78
-78
@@ -8,85 +8,85 @@ class Matrix4x4;
|
||||
class Quaternion
|
||||
{
|
||||
public:
|
||||
float x,y,z,w;
|
||||
float x,y,z,w;
|
||||
|
||||
Quaternion() { }
|
||||
Quaternion(const float _x, const float _y, const float _z, const float _w) {
|
||||
x=_x; y=_y; z=_z; w=_w;
|
||||
}
|
||||
void setIdentity()
|
||||
{
|
||||
x=y=z=0; w=1.0f;
|
||||
}
|
||||
void setXRotation(const float r) { w = cosf(r / 2); x = sinf(r / 2); y = z = 0; }
|
||||
void setYRotation(const float r) { w = cosf(r / 2); y = sinf(r / 2); x = z = 0; }
|
||||
void setZRotation(const float r) { w = cosf(r / 2); z = sinf(r / 2); x = y = 0; }
|
||||
void toMatrix(Matrix4x4 *out) const;
|
||||
static Quaternion fromMatrix(Matrix4x4 &m);
|
||||
Quaternion() { }
|
||||
Quaternion(const float _x, const float _y, const float _z, const float _w) {
|
||||
x=_x; y=_y; z=_z; w=_w;
|
||||
}
|
||||
void setIdentity()
|
||||
{
|
||||
x=y=z=0; w=1.0f;
|
||||
}
|
||||
void setXRotation(const float r) { w = cosf(r / 2); x = sinf(r / 2); y = z = 0; }
|
||||
void setYRotation(const float r) { w = cosf(r / 2); y = sinf(r / 2); x = z = 0; }
|
||||
void setZRotation(const float r) { w = cosf(r / 2); z = sinf(r / 2); x = y = 0; }
|
||||
void toMatrix(Matrix4x4 *out) const;
|
||||
static Quaternion fromMatrix(Matrix4x4 &m);
|
||||
|
||||
Quaternion operator *(Quaternion &q) const
|
||||
{
|
||||
return Quaternion(
|
||||
(w * q.w) - (x * q.x) - (y * q.y) - (z * q.z),
|
||||
(w * q.x) + (x * q.w) + (y * q.z) - (z * q.y),
|
||||
(w * q.y) + (y * q.w) + (z * q.x) - (x * q.z),
|
||||
(w * q.z) + (z * q.w) + (x * q.y) - (y * q.x)
|
||||
);
|
||||
}
|
||||
Quaternion operator -()
|
||||
{
|
||||
return Quaternion(-x,-y,-z,-w);
|
||||
}
|
||||
void setRotation(Vec3 axis, float angle)
|
||||
{
|
||||
axis /= axis.length();
|
||||
angle *= .5f;
|
||||
float sine = sinf(angle);
|
||||
w = cosf(angle);
|
||||
x = sine * axis.x;
|
||||
y = sine * axis.y;
|
||||
z = sine * axis.z;
|
||||
}
|
||||
void toAxisAngle(Vec3 &v, float &angle)
|
||||
{
|
||||
normalize();
|
||||
if (w==1.0f && x==0.0f && y==0.0f && z==0.0f)
|
||||
{
|
||||
v = Vec3(0,1,0);
|
||||
angle = 0.0f;
|
||||
return;
|
||||
}
|
||||
float cos_a = w;
|
||||
angle = acosf(cos_a) * 2;
|
||||
float sin_a = sqrtf( 1.0f - cos_a * cos_a );
|
||||
if (fabsf(sin_a) < 0.00005f) sin_a = 1;
|
||||
float inv_sin_a=1.0f/sin_a;
|
||||
v.x = x * inv_sin_a;
|
||||
v.y = y * inv_sin_a;
|
||||
v.z = z * inv_sin_a;
|
||||
}
|
||||
enum {
|
||||
QUAT_SHORT,
|
||||
QUAT_LONG,
|
||||
QUAT_CW,
|
||||
QUAT_CCW
|
||||
};
|
||||
Quaternion slerp(const Quaternion &to, const float a) const;
|
||||
Quaternion multiply(const Quaternion &q) const;
|
||||
float &operator [] (int i) {
|
||||
return *((&x) + i);
|
||||
}
|
||||
const float operator [] (int i) const {
|
||||
return *((&x) + i);
|
||||
}
|
||||
//not sure about this, maybe mag is supposed to sqrt
|
||||
float magnitude() const {
|
||||
return x*x + y*y + z*z + w*w;
|
||||
}
|
||||
void normalize() {
|
||||
float f = 1.0f/sqrtf(magnitude());
|
||||
x*=f; y*=f; z*=f; w*=f;
|
||||
}
|
||||
Quaternion operator *(Quaternion &q) const
|
||||
{
|
||||
return Quaternion(
|
||||
(w * q.w) - (x * q.x) - (y * q.y) - (z * q.z),
|
||||
(w * q.x) + (x * q.w) + (y * q.z) - (z * q.y),
|
||||
(w * q.y) + (y * q.w) + (z * q.x) - (x * q.z),
|
||||
(w * q.z) + (z * q.w) + (x * q.y) - (y * q.x)
|
||||
);
|
||||
}
|
||||
Quaternion operator -()
|
||||
{
|
||||
return Quaternion(-x,-y,-z,-w);
|
||||
}
|
||||
void setRotation(Vec3 axis, float angle)
|
||||
{
|
||||
axis /= axis.length();
|
||||
angle *= .5f;
|
||||
float sine = sinf(angle);
|
||||
w = cosf(angle);
|
||||
x = sine * axis.x;
|
||||
y = sine * axis.y;
|
||||
z = sine * axis.z;
|
||||
}
|
||||
void toAxisAngle(Vec3 &v, float &angle)
|
||||
{
|
||||
normalize();
|
||||
if (w==1.0f && x==0.0f && y==0.0f && z==0.0f)
|
||||
{
|
||||
v = Vec3(0,1,0);
|
||||
angle = 0.0f;
|
||||
return;
|
||||
}
|
||||
float cos_a = w;
|
||||
angle = acosf(cos_a) * 2;
|
||||
float sin_a = sqrtf( 1.0f - cos_a * cos_a );
|
||||
if (fabsf(sin_a) < 0.00005f) sin_a = 1;
|
||||
float inv_sin_a=1.0f/sin_a;
|
||||
v.x = x * inv_sin_a;
|
||||
v.y = y * inv_sin_a;
|
||||
v.z = z * inv_sin_a;
|
||||
}
|
||||
enum {
|
||||
QUAT_SHORT,
|
||||
QUAT_LONG,
|
||||
QUAT_CW,
|
||||
QUAT_CCW
|
||||
};
|
||||
Quaternion slerp(const Quaternion &to, const float a) const;
|
||||
Quaternion multiply(const Quaternion &q) const;
|
||||
float &operator [] (int i) {
|
||||
return *((&x) + i);
|
||||
}
|
||||
const float operator [] (int i) const {
|
||||
return *((&x) + i);
|
||||
}
|
||||
//not sure about this, maybe mag is supposed to sqrt
|
||||
float magnitude() const {
|
||||
return x*x + y*y + z*z + w*w;
|
||||
}
|
||||
void normalize() {
|
||||
float f = 1.0f/sqrtf(magnitude());
|
||||
x*=f; y*=f; z*=f; w*=f;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _MATH_LIN_QUAT_H
|
||||
#endif // _MATH_LIN_QUAT_H
|
||||
|
||||
+14
-14
@@ -4,25 +4,25 @@
|
||||
#include "math/lin/matrix4x4.h"
|
||||
|
||||
Vec3 Vec3::operator *(const Matrix4x4 &m) const {
|
||||
return Vec3(x*m.xx + y*m.yx + z*m.zx + m.wx,
|
||||
x*m.xy + y*m.yy + z*m.zy + m.wy,
|
||||
x*m.xz + y*m.yz + z*m.zz + m.wz);
|
||||
return Vec3(x*m.xx + y*m.yx + z*m.zx + m.wx,
|
||||
x*m.xy + y*m.yy + z*m.zy + m.wy,
|
||||
x*m.xz + y*m.yz + z*m.zz + m.wz);
|
||||
}
|
||||
Vec4 Vec3::multiply4D(const Matrix4x4 &m) const {
|
||||
return Vec4(x*m.xx + y*m.yx + z*m.zx + m.wx,
|
||||
x*m.xy + y*m.yy + z*m.zy + m.wy,
|
||||
x*m.xz + y*m.yz + z*m.zz + m.wz,
|
||||
x*m.xw + y*m.yw + z*m.zw + m.ww);
|
||||
return Vec4(x*m.xx + y*m.yx + z*m.zx + m.wx,
|
||||
x*m.xy + y*m.yy + z*m.zy + m.wy,
|
||||
x*m.xz + y*m.yz + z*m.zz + m.wz,
|
||||
x*m.xw + y*m.yw + z*m.zw + m.ww);
|
||||
}
|
||||
Vec4 Vec4::multiply4D(Matrix4x4 &m) const {
|
||||
return Vec4(x*m.xx + y*m.yx + z*m.zx + w*m.wx,
|
||||
x*m.xy + y*m.yy + z*m.zy + w*m.wy,
|
||||
x*m.xz + y*m.yz + z*m.zz + w*m.wz,
|
||||
x*m.xw + y*m.yw + z*m.zw + w*m.ww);
|
||||
return Vec4(x*m.xx + y*m.yx + z*m.zx + w*m.wx,
|
||||
x*m.xy + y*m.yy + z*m.zy + w*m.wy,
|
||||
x*m.xz + y*m.yz + z*m.zz + w*m.wz,
|
||||
x*m.xw + y*m.yw + z*m.zw + w*m.ww);
|
||||
}
|
||||
|
||||
Vec3 Vec3::rotatedBy(const Matrix4x4 &m) const {
|
||||
return Vec3(x*m.xx + y*m.yx + z*m.zx,
|
||||
x*m.xy + y*m.yy + z*m.zy,
|
||||
x*m.xz + y*m.yz + z*m.zz);
|
||||
return Vec3(x*m.xx + y*m.yx + z*m.zx,
|
||||
x*m.xy + y*m.yy + z*m.zy,
|
||||
x*m.xz + y*m.yz + z*m.zz);
|
||||
}
|
||||
|
||||
+108
-108
@@ -2,122 +2,122 @@
|
||||
#define _MATH_LIN_VEC3
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h> // memset
|
||||
#include <string.h> // memset
|
||||
|
||||
class Matrix4x4;
|
||||
|
||||
// Hm, doesn't belong in this file.
|
||||
class Vec4 {
|
||||
public:
|
||||
float x,y,z,w;
|
||||
Vec4(){}
|
||||
Vec4(float a, float b, float c, float d) {x=a;y=b;z=c;w=d;}
|
||||
Vec4 multiply4D(Matrix4x4 &m) const;
|
||||
float x,y,z,w;
|
||||
Vec4(){}
|
||||
Vec4(float a, float b, float c, float d) {x=a;y=b;z=c;w=d;}
|
||||
Vec4 multiply4D(Matrix4x4 &m) const;
|
||||
};
|
||||
|
||||
class Vec3 {
|
||||
public:
|
||||
float x,y,z;
|
||||
float x,y,z;
|
||||
|
||||
Vec3() { }
|
||||
explicit Vec3(float f) {x=y=z=f;}
|
||||
Vec3() { }
|
||||
explicit Vec3(float f) {x=y=z=f;}
|
||||
|
||||
float operator [] (int i) const { return (&x)[i]; }
|
||||
float &operator [] (int i) { return (&x)[i]; }
|
||||
float operator [] (int i) const { return (&x)[i]; }
|
||||
float &operator [] (int i) { return (&x)[i]; }
|
||||
|
||||
Vec3(const float _x, const float _y, const float _z) {
|
||||
x=_x; y=_y; z=_z;
|
||||
}
|
||||
void Set(float _x, float _y, float _z) {
|
||||
x=_x; y=_y; z=_z;
|
||||
}
|
||||
Vec3 operator + (const Vec3 &other) const {
|
||||
return Vec3(x+other.x, y+other.y, z+other.z);
|
||||
}
|
||||
void operator += (const Vec3 &other) {
|
||||
x+=other.x; y+=other.y; z+=other.z;
|
||||
}
|
||||
Vec3 operator -(const Vec3 &v) const {
|
||||
return Vec3(x-v.x,y-v.y,z-v.z);
|
||||
}
|
||||
void operator -= (const Vec3 &other)
|
||||
{
|
||||
x-=other.x; y-=other.y; z-=other.z;
|
||||
}
|
||||
Vec3 operator -() const {
|
||||
return Vec3(-x,-y,-z);
|
||||
}
|
||||
Vec3(const float _x, const float _y, const float _z) {
|
||||
x=_x; y=_y; z=_z;
|
||||
}
|
||||
void Set(float _x, float _y, float _z) {
|
||||
x=_x; y=_y; z=_z;
|
||||
}
|
||||
Vec3 operator + (const Vec3 &other) const {
|
||||
return Vec3(x+other.x, y+other.y, z+other.z);
|
||||
}
|
||||
void operator += (const Vec3 &other) {
|
||||
x+=other.x; y+=other.y; z+=other.z;
|
||||
}
|
||||
Vec3 operator -(const Vec3 &v) const {
|
||||
return Vec3(x-v.x,y-v.y,z-v.z);
|
||||
}
|
||||
void operator -= (const Vec3 &other)
|
||||
{
|
||||
x-=other.x; y-=other.y; z-=other.z;
|
||||
}
|
||||
Vec3 operator -() const {
|
||||
return Vec3(-x,-y,-z);
|
||||
}
|
||||
|
||||
Vec3 operator * (const float f) const {
|
||||
return Vec3(x*f,y*f,z*f);
|
||||
}
|
||||
Vec3 operator / (const float f) const {
|
||||
float invf = (1.0f/f);
|
||||
return Vec3(x*invf,y*invf,z*invf);
|
||||
}
|
||||
void operator /= (const float f)
|
||||
{
|
||||
*this = *this / f;
|
||||
}
|
||||
float operator * (const Vec3 &other) const {
|
||||
return x*other.x + y*other.y + z*other.z;
|
||||
}
|
||||
void operator *= (const float f) {
|
||||
*this = *this * f;
|
||||
}
|
||||
void scaleBy(const Vec3 &other) {
|
||||
x *= other.x; y *= other.y; z *= other.z;
|
||||
}
|
||||
Vec3 scaledBy(const Vec3 &other) const {
|
||||
return Vec3(x*other.x, y*other.y, z*other.z);
|
||||
}
|
||||
Vec3 scaledByInv(const Vec3 &other) const {
|
||||
return Vec3(x/other.x, y/other.y, z/other.z);
|
||||
}
|
||||
Vec3 operator *(const Matrix4x4 &m) const;
|
||||
void operator *=(const Matrix4x4 &m) {
|
||||
*this = *this * m;
|
||||
}
|
||||
Vec4 multiply4D(const Matrix4x4 &m) const;
|
||||
Vec3 rotatedBy(const Matrix4x4 &m) const;
|
||||
Vec3 operator %(const Vec3 &v) const {
|
||||
return Vec3(y*v.z-z*v.y, z*v.x-x*v.z, x*v.y-y*v.x);
|
||||
}
|
||||
float length2() const {
|
||||
return x*x + y*y + z*z;
|
||||
}
|
||||
float length() const {
|
||||
return sqrtf(length2());
|
||||
}
|
||||
void setLength(const float l) {
|
||||
(*this) *= l/length();
|
||||
}
|
||||
Vec3 withLength(const float l) const {
|
||||
return (*this) * l / length();
|
||||
}
|
||||
float distance2To(const Vec3 &other) const {
|
||||
return Vec3(other-(*this)).length2();
|
||||
}
|
||||
Vec3 normalized() const {
|
||||
return (*this) / length();
|
||||
}
|
||||
float normalize() { //returns the previous length, is often useful
|
||||
float len = length();
|
||||
(*this) = (*this)/len;
|
||||
return len;
|
||||
}
|
||||
bool operator == (const Vec3 &other) const {
|
||||
if (x==other.x && y==other.y && z==other.z)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
Vec3 lerp(const Vec3 &other, const float t) const {
|
||||
return (*this)*(1-t) + other*t;
|
||||
}
|
||||
void setZero() {
|
||||
memset((void *)this,0,sizeof(float)*3);
|
||||
}
|
||||
Vec3 operator * (const float f) const {
|
||||
return Vec3(x*f,y*f,z*f);
|
||||
}
|
||||
Vec3 operator / (const float f) const {
|
||||
float invf = (1.0f/f);
|
||||
return Vec3(x*invf,y*invf,z*invf);
|
||||
}
|
||||
void operator /= (const float f)
|
||||
{
|
||||
*this = *this / f;
|
||||
}
|
||||
float operator * (const Vec3 &other) const {
|
||||
return x*other.x + y*other.y + z*other.z;
|
||||
}
|
||||
void operator *= (const float f) {
|
||||
*this = *this * f;
|
||||
}
|
||||
void scaleBy(const Vec3 &other) {
|
||||
x *= other.x; y *= other.y; z *= other.z;
|
||||
}
|
||||
Vec3 scaledBy(const Vec3 &other) const {
|
||||
return Vec3(x*other.x, y*other.y, z*other.z);
|
||||
}
|
||||
Vec3 scaledByInv(const Vec3 &other) const {
|
||||
return Vec3(x/other.x, y/other.y, z/other.z);
|
||||
}
|
||||
Vec3 operator *(const Matrix4x4 &m) const;
|
||||
void operator *=(const Matrix4x4 &m) {
|
||||
*this = *this * m;
|
||||
}
|
||||
Vec4 multiply4D(const Matrix4x4 &m) const;
|
||||
Vec3 rotatedBy(const Matrix4x4 &m) const;
|
||||
Vec3 operator %(const Vec3 &v) const {
|
||||
return Vec3(y*v.z-z*v.y, z*v.x-x*v.z, x*v.y-y*v.x);
|
||||
}
|
||||
float length2() const {
|
||||
return x*x + y*y + z*z;
|
||||
}
|
||||
float length() const {
|
||||
return sqrtf(length2());
|
||||
}
|
||||
void setLength(const float l) {
|
||||
(*this) *= l/length();
|
||||
}
|
||||
Vec3 withLength(const float l) const {
|
||||
return (*this) * l / length();
|
||||
}
|
||||
float distance2To(const Vec3 &other) const {
|
||||
return Vec3(other-(*this)).length2();
|
||||
}
|
||||
Vec3 normalized() const {
|
||||
return (*this) / length();
|
||||
}
|
||||
float normalize() { //returns the previous length, is often useful
|
||||
float len = length();
|
||||
(*this) = (*this)/len;
|
||||
return len;
|
||||
}
|
||||
bool operator == (const Vec3 &other) const {
|
||||
if (x==other.x && y==other.y && z==other.z)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
Vec3 lerp(const Vec3 &other, const float t) const {
|
||||
return (*this)*(1-t) + other*t;
|
||||
}
|
||||
void setZero() {
|
||||
memset((void *)this,0,sizeof(float)*3);
|
||||
}
|
||||
};
|
||||
|
||||
inline Vec3 operator * (const float f, const Vec3 &v) {return v * f;}
|
||||
@@ -125,21 +125,21 @@ inline Vec3 operator * (const float f, const Vec3 &v) {return v * f;}
|
||||
// In new code, prefer these to the operators.
|
||||
|
||||
inline float dot(const Vec3 &a, const Vec3 &b) {
|
||||
return a.x * b.x + a.y * b.y + a.z * b.z;
|
||||
return a.x * b.x + a.y * b.y + a.z * b.z;
|
||||
}
|
||||
|
||||
inline Vec3 cross(const Vec3 &a, const Vec3 &b) {
|
||||
return a % b;
|
||||
return a % b;
|
||||
}
|
||||
|
||||
inline float sqr(const Vec3 &v) {
|
||||
return dot(v, v);
|
||||
return dot(v, v);
|
||||
}
|
||||
|
||||
class AABBox {
|
||||
public:
|
||||
Vec3 min;
|
||||
Vec3 max;
|
||||
Vec3 min;
|
||||
Vec3 max;
|
||||
};
|
||||
|
||||
#endif // _MATH_LIN_VEC3
|
||||
#endif // _MATH_LIN_VEC3
|
||||
|
||||
+14
-14
@@ -3,7 +3,7 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
/*
|
||||
static unsigned int randSeed = 22222; // Change this for different random sequences.
|
||||
static unsigned int randSeed = 22222; // Change this for different random sequences.
|
||||
|
||||
void SetSeed(unsigned int seed) {
|
||||
randSeed = seed * 382792592;
|
||||
@@ -21,22 +21,22 @@ unsigned int GenerateRandomNumber() {
|
||||
|
||||
void EnableFZ()
|
||||
{
|
||||
int x;
|
||||
asm(
|
||||
"fmrx %[result],FPSCR \r\n"
|
||||
"orr %[result],%[result],#16777216 \r\n"
|
||||
"fmxr FPSCR,%[result]"
|
||||
:[result] "=r" (x) : :
|
||||
);
|
||||
//printf("ARM FPSCR: %08x\n",x);
|
||||
int x;
|
||||
asm(
|
||||
"fmrx %[result],FPSCR \r\n"
|
||||
"orr %[result],%[result],#16777216 \r\n"
|
||||
"fmxr FPSCR,%[result]"
|
||||
:[result] "=r" (x) : :
|
||||
);
|
||||
//printf("ARM FPSCR: %08x\n",x);
|
||||
}
|
||||
|
||||
void DisableFZ( )
|
||||
{
|
||||
__asm__ volatile(
|
||||
"fmrx r0, fpscr\n"
|
||||
"bic r0, $(1 << 24)\n"
|
||||
"fmxr fpscr, r0" : : : "r0");
|
||||
__asm__ volatile(
|
||||
"fmrx r0, fpscr\n"
|
||||
"bic r0, $(1 << 24)\n"
|
||||
"fmxr fpscr, r0" : : : "r0");
|
||||
}
|
||||
#else
|
||||
|
||||
@@ -50,4 +50,4 @@ void DisableFZ()
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
+20
-20
@@ -4,7 +4,7 @@
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
|
||||
inline float sqr(float f) {return f*f;}
|
||||
inline float sqr(float f) {return f*f;}
|
||||
inline float sqr_signed(float f) {return f<0 ? -f*f : f*f;}
|
||||
|
||||
typedef unsigned short float16;
|
||||
@@ -13,15 +13,15 @@ typedef unsigned short float16;
|
||||
// This choice is subject to change. Don't think I'm using this for anything at all now anyway.
|
||||
// DEPRECATED
|
||||
inline float16 FloatToFloat16(float x) {
|
||||
int ix;
|
||||
memcpy(&ix, &x, sizeof(float));
|
||||
return ix >> 16;
|
||||
int ix;
|
||||
memcpy(&ix, &x, sizeof(float));
|
||||
return ix >> 16;
|
||||
}
|
||||
|
||||
inline float Float16ToFloat(float16 ix) {
|
||||
float x;
|
||||
memcpy(&x, &ix, sizeof(float));
|
||||
return x;
|
||||
float x;
|
||||
memcpy(&x, &ix, sizeof(float));
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
@@ -37,40 +37,40 @@ inline float Float16ToFloat(float16 ix) {
|
||||
void SetSeed(unsigned int seed);
|
||||
unsigned int GenerateRandomNumber();
|
||||
inline float GenerateRandomFloat01() {
|
||||
return (float)((double)GenerateRandomNumber() / 0xFFFFFFFF);
|
||||
return (float)((double)GenerateRandomNumber() / 0xFFFFFFFF);
|
||||
}
|
||||
inline float GenerateRandomSignedFloat() {
|
||||
return (float)((double)GenerateRandomNumber() / 0x80000000) - 1.0f;
|
||||
return (float)((double)GenerateRandomNumber() / 0x80000000) - 1.0f;
|
||||
}
|
||||
|
||||
|
||||
inline float GaussRand()
|
||||
{
|
||||
float R1 = GenerateRandomFloat01();
|
||||
float R2 = GenerateRandomFloat01();
|
||||
float R1 = GenerateRandomFloat01();
|
||||
float R2 = GenerateRandomFloat01();
|
||||
|
||||
float X = sqrtf(-2.0f * logf(R1)) * cosf(2.0f * PI * R2);
|
||||
if (X > 4.0f) X = 4.0f;
|
||||
if (X < -4.0f) X = -4.0f;
|
||||
return X;
|
||||
float X = sqrtf(-2.0f * logf(R1)) * cosf(2.0f * PI * R2);
|
||||
if (X > 4.0f) X = 4.0f;
|
||||
if (X < -4.0f) X = -4.0f;
|
||||
return X;
|
||||
}
|
||||
|
||||
// Accuracy unknown
|
||||
inline double atan_fast(double x) {
|
||||
return (x / (1.0 + 0.28 * (x * x)));
|
||||
return (x / (1.0 + 0.28 * (x * x)));
|
||||
}
|
||||
|
||||
|
||||
// linear -> dB conversion
|
||||
inline float lin2dB(float lin) {
|
||||
const float LOG_2_DB = 8.6858896380650365530225783783321f; // 20 / ln( 10 )
|
||||
return logf(lin) * LOG_2_DB;
|
||||
const float LOG_2_DB = 8.6858896380650365530225783783321f; // 20 / ln( 10 )
|
||||
return logf(lin) * LOG_2_DB;
|
||||
}
|
||||
|
||||
// dB -> linear conversion
|
||||
inline float dB2lin(float dB) {
|
||||
const float DB_2_LOG = 0.11512925464970228420089957273422f; // ln( 10 ) / 20
|
||||
return expf(dB * DB_2_LOG);
|
||||
const float DB_2_LOG = 0.11512925464970228420089957273422f; // ln( 10 ) / 20
|
||||
return expf(dB * DB_2_LOG);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+75
-75
@@ -27,62 +27,62 @@
|
||||
namespace net {
|
||||
|
||||
Connection::Connection()
|
||||
: port_(-1), sock_(-1) {
|
||||
: port_(-1), sock_(-1) {
|
||||
}
|
||||
|
||||
Connection::~Connection() {
|
||||
Disconnect();
|
||||
Disconnect();
|
||||
}
|
||||
|
||||
bool Connection::Resolve(const char *host, int port) {
|
||||
CHECK_EQ(-1, (intptr_t)sock_);
|
||||
host_ = host;
|
||||
port_ = port;
|
||||
CHECK_EQ(-1, (intptr_t)sock_);
|
||||
host_ = host;
|
||||
port_ = port;
|
||||
|
||||
const char *ip = net::DNSResolve(host);
|
||||
// VLOG(1) << "Resolved " << host << " to " << ip;
|
||||
remote_.sin_family = AF_INET;
|
||||
int tmpres = inet_pton(AF_INET, ip, (void *)(&(remote_.sin_addr.s_addr)));
|
||||
CHECK_GE(tmpres, 0); // << "inet_pton failed";
|
||||
CHECK_NE(0, tmpres); // << ip << " not a valid IP address";
|
||||
remote_.sin_port = htons(port);
|
||||
free((void *)ip);
|
||||
return true;
|
||||
const char *ip = net::DNSResolve(host);
|
||||
// VLOG(1) << "Resolved " << host << " to " << ip;
|
||||
remote_.sin_family = AF_INET;
|
||||
int tmpres = inet_pton(AF_INET, ip, (void *)(&(remote_.sin_addr.s_addr)));
|
||||
CHECK_GE(tmpres, 0); // << "inet_pton failed";
|
||||
CHECK_NE(0, tmpres); // << ip << " not a valid IP address";
|
||||
remote_.sin_port = htons(port);
|
||||
free((void *)ip);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Connection::Connect() {
|
||||
CHECK_GE(port_, 0);
|
||||
sock_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
CHECK_GE(sock_, 0);
|
||||
CHECK_GE(port_, 0);
|
||||
sock_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
CHECK_GE(sock_, 0);
|
||||
|
||||
// poll once per second.. should find a way to do this blocking.
|
||||
int retval = -1;
|
||||
while (retval < 0) {
|
||||
retval = connect(sock_, (sockaddr *)&remote_, sizeof(struct sockaddr));
|
||||
if (retval >= 0) break;
|
||||
// poll once per second.. should find a way to do this blocking.
|
||||
int retval = -1;
|
||||
while (retval < 0) {
|
||||
retval = connect(sock_, (sockaddr *)&remote_, sizeof(struct sockaddr));
|
||||
if (retval >= 0) break;
|
||||
#ifdef _WIN32
|
||||
Sleep(1);
|
||||
Sleep(1);
|
||||
#else
|
||||
sleep(1);
|
||||
sleep(1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Connection::Disconnect() {
|
||||
if ((intptr_t)sock_ != -1) {
|
||||
closesocket(sock_);
|
||||
sock_ = -1;
|
||||
} else {
|
||||
WLOG("Socket was already disconnected.");
|
||||
}
|
||||
if ((intptr_t)sock_ != -1) {
|
||||
closesocket(sock_);
|
||||
sock_ = -1;
|
||||
} else {
|
||||
WLOG("Socket was already disconnected.");
|
||||
}
|
||||
}
|
||||
|
||||
void Connection::Reconnect() {
|
||||
Disconnect();
|
||||
Connect();
|
||||
Disconnect();
|
||||
Connect();
|
||||
}
|
||||
|
||||
} // net
|
||||
} // net
|
||||
|
||||
namespace http {
|
||||
|
||||
@@ -94,55 +94,55 @@ Client::~Client() {
|
||||
#define USERAGENT "METAGET 1.0"
|
||||
|
||||
void Client::GET(const char *resource, Buffer *output) {
|
||||
Buffer buffer;
|
||||
const char *tpl = "GET %s HTTP/1.0\r\nHost: %s\r\n\r\n";
|
||||
buffer.Printf(tpl, resource, host_.c_str());
|
||||
CHECK(buffer.FlushSocket(sock()));
|
||||
Buffer buffer;
|
||||
const char *tpl = "GET %s HTTP/1.0\r\nHost: %s\r\n\r\n";
|
||||
buffer.Printf(tpl, resource, host_.c_str());
|
||||
CHECK(buffer.FlushSocket(sock()));
|
||||
|
||||
// Snarf all the data we can.
|
||||
output->ReadAll(sock());
|
||||
// Snarf all the data we can.
|
||||
output->ReadAll(sock());
|
||||
|
||||
// Skip the header.
|
||||
while (output->SkipLineCRLF() > 0)
|
||||
;
|
||||
// Skip the header.
|
||||
while (output->SkipLineCRLF() > 0)
|
||||
;
|
||||
|
||||
// output now contains the rest of the reply.
|
||||
// output now contains the rest of the reply.
|
||||
}
|
||||
|
||||
int Client::POST(const char *resource, const std::string &data, Buffer *output) {
|
||||
Buffer buffer;
|
||||
const char *tpl = "POST %s HTTP/1.0\r\nContent-Length: %d\r\n\r\n";
|
||||
buffer.Printf(tpl, resource, (int)data.size());
|
||||
buffer.Append(data);
|
||||
CHECK(buffer.Flush(sock()));
|
||||
Buffer buffer;
|
||||
const char *tpl = "POST %s HTTP/1.0\r\nContent-Length: %d\r\n\r\n";
|
||||
buffer.Printf(tpl, resource, (int)data.size());
|
||||
buffer.Append(data);
|
||||
CHECK(buffer.Flush(sock()));
|
||||
|
||||
// I guess we could add a deadline here.
|
||||
output->ReadAll(sock());
|
||||
// I guess we could add a deadline here.
|
||||
output->ReadAll(sock());
|
||||
|
||||
if (output->size() == 0) {
|
||||
// The connection was closed.
|
||||
ELOG("POST failed.");
|
||||
return -1;
|
||||
}
|
||||
if (output->size() == 0) {
|
||||
// The connection was closed.
|
||||
ELOG("POST failed.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::string debug_data;
|
||||
output->PeekAll(&debug_data);
|
||||
|
||||
//VLOG(1) << "Reply size (before stripping headers): " << debug_data.size();
|
||||
std::string debug_str;
|
||||
StringToHexString(debug_data, &debug_str);
|
||||
// Tear off the http headers, leaving the actual response data.
|
||||
std::string firstline;
|
||||
CHECK_GT(output->TakeLineCRLF(&firstline), 0);
|
||||
int code = atoi(&firstline[9]); // ugggly hardcoding
|
||||
//VLOG(1) << "HTTP result code: " << code;
|
||||
while (true) {
|
||||
int skipped = output->SkipLineCRLF();
|
||||
if (skipped == 0)
|
||||
break;
|
||||
}
|
||||
output->PeekAll(&debug_data);
|
||||
return code;
|
||||
std::string debug_data;
|
||||
output->PeekAll(&debug_data);
|
||||
|
||||
//VLOG(1) << "Reply size (before stripping headers): " << debug_data.size();
|
||||
std::string debug_str;
|
||||
StringToHexString(debug_data, &debug_str);
|
||||
// Tear off the http headers, leaving the actual response data.
|
||||
std::string firstline;
|
||||
CHECK_GT(output->TakeLineCRLF(&firstline), 0);
|
||||
int code = atoi(&firstline[9]); // ugggly hardcoding
|
||||
//VLOG(1) << "HTTP result code: " << code;
|
||||
while (true) {
|
||||
int skipped = output->SkipLineCRLF();
|
||||
if (skipped == 0)
|
||||
break;
|
||||
}
|
||||
output->PeekAll(&debug_data);
|
||||
return code;
|
||||
}
|
||||
|
||||
} // http
|
||||
} // http
|
||||
|
||||
+30
-30
@@ -14,53 +14,53 @@
|
||||
namespace net {
|
||||
|
||||
class Connection {
|
||||
public:
|
||||
Connection();
|
||||
virtual ~Connection();
|
||||
public:
|
||||
Connection();
|
||||
virtual ~Connection();
|
||||
|
||||
// Inits the sockaddr_in.
|
||||
bool Resolve(const char *host, int port);
|
||||
// Inits the sockaddr_in.
|
||||
bool Resolve(const char *host, int port);
|
||||
|
||||
void Connect();
|
||||
void Disconnect();
|
||||
void Connect();
|
||||
void Disconnect();
|
||||
|
||||
// Disconnects, and connects. Doesn't re-resolve.
|
||||
void Reconnect();
|
||||
// Disconnects, and connects. Doesn't re-resolve.
|
||||
void Reconnect();
|
||||
|
||||
// Only to be used for bring-up and debugging.
|
||||
uintptr_t sock() const { return sock_; }
|
||||
// Only to be used for bring-up and debugging.
|
||||
uintptr_t sock() const { return sock_; }
|
||||
|
||||
protected:
|
||||
// Store the remote host here, so we can send it along through HTTP/1.1 requests.
|
||||
// TODO: Move to http::client?
|
||||
std::string host_;
|
||||
int port_;
|
||||
|
||||
sockaddr_in remote_;
|
||||
protected:
|
||||
// Store the remote host here, so we can send it along through HTTP/1.1 requests.
|
||||
// TODO: Move to http::client?
|
||||
std::string host_;
|
||||
int port_;
|
||||
|
||||
private:
|
||||
uintptr_t sock_;
|
||||
sockaddr_in remote_;
|
||||
|
||||
private:
|
||||
uintptr_t sock_;
|
||||
|
||||
};
|
||||
|
||||
} // namespace net
|
||||
} // namespace net
|
||||
|
||||
namespace http {
|
||||
|
||||
class Client : public net::Connection {
|
||||
public:
|
||||
Client();
|
||||
~Client();
|
||||
public:
|
||||
Client();
|
||||
~Client();
|
||||
|
||||
void GET(const char *resource, Buffer *output);
|
||||
void GET(const char *resource, Buffer *output);
|
||||
|
||||
// Return value is the HTTP return code.
|
||||
int POST(const char *resource, const std::string &data, Buffer *output);
|
||||
// Return value is the HTTP return code.
|
||||
int POST(const char *resource, const std::string &data, Buffer *output);
|
||||
|
||||
// HEAD, PUT, DELETE aren't implemented yet.
|
||||
// HEAD, PUT, DELETE aren't implemented yet.
|
||||
};
|
||||
|
||||
} // http
|
||||
} // http
|
||||
|
||||
#endif // _NET_HTTP_HTTP_CLIENT
|
||||
#endif // _NET_HTTP_HTTP_CLIENT
|
||||
|
||||
|
||||
+20
-20
@@ -1,4 +1,4 @@
|
||||
#include "net/resolve.h"
|
||||
#include "net/resolve.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h> // gethostbyname
|
||||
#include <netdb.h> // gethostbyname
|
||||
#include <sys/socket.h>
|
||||
#else
|
||||
#include <WinSock2.h>
|
||||
@@ -22,35 +22,35 @@ namespace net {
|
||||
void Init()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
WSADATA wsaData = {0};
|
||||
WSAStartup(MAKEWORD(2, 2), &wsaData);
|
||||
WSADATA wsaData = {0};
|
||||
WSAStartup(MAKEWORD(2, 2), &wsaData);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Shutdown()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
WSACleanup();
|
||||
WSACleanup();
|
||||
#endif
|
||||
}
|
||||
|
||||
char *DNSResolve(const char *host)
|
||||
{
|
||||
struct hostent *hent;
|
||||
if((hent = gethostbyname(host)) == NULL)
|
||||
{
|
||||
perror("Can't get IP");
|
||||
exit(1);
|
||||
}
|
||||
int iplen = 15; //XXX.XXX.XXX.XXX
|
||||
char *ip = (char *)malloc(iplen+1);
|
||||
memset(ip, 0, iplen+1);
|
||||
if(inet_ntop(AF_INET, (void *)hent->h_addr_list[0], ip, iplen) == NULL)
|
||||
{
|
||||
perror("Can't resolve host");
|
||||
exit(1);
|
||||
}
|
||||
return ip;
|
||||
struct hostent *hent;
|
||||
if((hent = gethostbyname(host)) == NULL)
|
||||
{
|
||||
perror("Can't get IP");
|
||||
exit(1);
|
||||
}
|
||||
int iplen = 15; //XXX.XXX.XXX.XXX
|
||||
char *ip = (char *)malloc(iplen+1);
|
||||
memset(ip, 0, iplen+1);
|
||||
if(inet_ntop(AF_INET, (void *)hent->h_addr_list[0], ip, iplen) == NULL)
|
||||
{
|
||||
perror("Can't resolve host");
|
||||
exit(1);
|
||||
}
|
||||
return ip;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user