Reindent (->tabs)

This commit is contained in:
Henrik Rydgård
2012-10-30 13:20:55 +01:00
parent edb0e8e8b2
commit 5a5f599e1b
52 changed files with 2584 additions and 2586 deletions
+135 -135
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -11,7 +11,7 @@
#endif
#define DISALLOW_COPY_AND_ASSIGN(t) \
private: \
private: \
t(const t &other); \
void operator =(const t &other);
+59 -59
View File
@@ -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
View File
@@ -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
View File
@@ -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]);
}
}
}
+5 -5
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
+2 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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;
}
}
+9 -9
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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;
}
}