Merge branch 'master' of github.com:hrydgard/native

This commit is contained in:
Henrik Rydgard committed 2012-07-05 23:30:47 +02:00
commit ee2dfaba5a
76 files changed
+3227 -2291

No files matched your search

+17 -6
View File
@@ -20,9 +20,10 @@
#include "file/zip_read.h"
#include "input/input_state.h"
#include "audio/mixer.h"
#include "math/math_util.h"
#define coord_xres 800
#define coord_yres 480
#define coord_xres 480
#define coord_yres 800
static JNIEnv *jniEnvUI;
@@ -97,6 +98,13 @@ extern "C" void Java_com_turboviking_libnative_NativeApp_init
yres = yyres;
g_xres = xres;
g_yres = yres;
if (g_xres < g_yres)
{
// Portrait - let's force the imaginary resolution we want
g_xres = coord_xres;
g_yres = coord_yres;
}
xscale = (float)coord_xres / xres;
yscale = (float)coord_yres / yres;
memset(&input_state, 0, sizeof(input_state));
@@ -189,6 +197,9 @@ extern "C" void Java_com_turboviking_libnative_NativeRenderer_displayRender
}
extern "C" void Java_com_turboviking_libnative_NativeApp_audioRender(JNIEnv* env, jclass clazz, jshortArray array) {
// The audio thread can pretty safely enable Flush-to-Zero mode on the FPU.
EnableFZ();
int buf_size = env->GetArrayLength(array);
if (buf_size) {
short *data = env->GetShortArrayElements(array, 0);
@@ -207,14 +218,14 @@ extern "C" void JNICALL Java_com_turboviking_libnative_NativeApp_touch
return; // We ignore 8+ pointers entirely.
}
input_state.mouse_x[pointerId] = (int)x;
input_state.mouse_y[pointerId] = (int)y;
input_state.mouse_x[pointerId] = (int)(x * xscale);
input_state.mouse_y[pointerId] = (int)(y * yscale);
if (code == 1) {
ILOG("Down: %i %f %f", pointerId, x, y);
//ILOG("Down: %i %f %f", pointerId, x, y);
input_state.mouse_last[pointerId] = input_state.mouse_down[pointerId];
input_state.mouse_down[pointerId] = true;
} else if (code == 2) {
ILOG("Up: %i %f %f", pointerId, x, y);
//ILOG("Up: %i %f %f", pointerId, x, y);
input_state.mouse_last[pointerId] = input_state.mouse_down[pointerId];
input_state.mouse_down[pointerId] = false;
}
@@ -16,4 +16,4 @@ public class NativeApp {
// Sensor/input data. These are asynchronous, beware!
public static native void touch(float x, float y, int data, int pointerId);
public static native void accelerometer(float x, float y, float z);
}
}
@@ -37,6 +37,7 @@ public class NativeAudioPlayer {
playThread();
}
});
thread.setPriority(Thread.MAX_PRIORITY);
thread.start();
}
+26 -21
View File
@@ -33,7 +33,7 @@ struct Clip {
// If current_clip == 0, the channel is free.
enum PlaybackState {
enum ClipPlaybackState {
PB_STOPPED = 0,
PB_PLAYING = 1,
};
@@ -42,7 +42,7 @@ enum PlaybackState {
struct Channel {
const Clip *current_clip;
// Playback state
PlaybackState state;
ClipPlaybackState state;
int pos;
PlayParams params;
// Effect state
@@ -89,26 +89,26 @@ static int get_free_channel(Mixer *mixer) {
}
Clip *clip_load(const char *filename) {
short *data;
short *data;
int num_samples, 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;
@@ -130,7 +130,12 @@ void clip_destroy(Clip *clip) {
}
}
int clip_length(const Clip *clip) {
const short *clip_data(const Clip *clip)
{
return clip->data;
}
size_t clip_length(const Clip *clip) {
return clip->length;
}
+5 -3
View File
@@ -1,8 +1,9 @@
#pragma once
#include "base/basictypes.h"
// Simple mixer intended for sound effects for games.
// Intended both for fire and forget sfx (auto channels) and for
// realtime-modifiable sounds like pitched engine noises (fixed channels).
// The clip loading code supports ogg SFX.
struct Mixer;
struct Clip;
@@ -30,7 +31,8 @@ void mixer_mix(Mixer *mixer, short *buffer, int num_samples);
Clip *clip_load(const char *filename);
void clip_destroy(Clip *clip);
int clip_length();
const short *clip_data(const Clip *clip);
size_t clip_length(const Clip *clip);
void clip_set_loop(int start, int end);
+6 -8
View File
@@ -4,8 +4,9 @@
#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);
@@ -16,10 +17,8 @@ short *wav_read(const char *filename,
int samplesPerSec, avgBytesPerSec,wBlockAlign,wBytesPerSample;
if (cf.descend('RIFF')) {
cf.readInt(); //get past 'WAVE'
if (cf.descend('fmt ')) //enter the format chunk
{
int temp;
temp = cf.readInt();
if (cf.descend('fmt ')) { //enter the format chunk
int temp = cf.readInt();
int format = temp & 0xFFFF;
if (format != 1) {
cf.ascend();
@@ -42,8 +41,7 @@ short *wav_read(const char *filename,
return NULL;
}
if (cf.descend('data')) //enter the data chunk
{
if (cf.descend('data')) { //enter the data chunk
int numBytes = cf.getCurrentChunkSize();
int numSamples = numBytes / wBlockAlign;
data = (short *)malloc(sizeof(short) * numSamples * *num_channels);
+2 -1
View File
@@ -2,7 +2,8 @@ set(SRCS
LAMEString.cpp
colorutil.cpp
error_context.cpp
display.cpp)
display.cpp
buffer.cpp)
set(SRCS ${SRCS})
+3 -2
View File
@@ -1,6 +1,7 @@
// NOTE: This is only here for legacy reasons.
// In new code, please use std::string.
// DEPRECATED
// This is only here for legacy reasons.
// In new code, please use std::string.
#pragma once
+18 -5
View File
@@ -23,6 +23,7 @@
#include "file/zip_read.h"
#include "input/input_state.h"
#include "base/NativeApp.h"
#include "net/resolve.h"
// Simple implementations of System functions
@@ -131,10 +132,14 @@ int main(int argc, char *argv[]) {
g_xres = 800;
g_yres = 480;
} else {
g_xres = 1480;
g_yres = 800;
#ifdef _WIN32
g_xres = 1580;
g_yres = 1000;
#endif
}
net::Init();
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
fprintf(stderr, "Unable to initialize SDL: %s\n", SDL_GetError());
return 1;
@@ -208,13 +213,15 @@ int main(int argc, char *argv[]) {
InputState input_state;
int framecount = 0;
bool nextFrameMD = 0;
while (true) {
SDL_Event event;
input_state.accelerometer_valid = false;
input_state.mouse_valid = true;
int done = 0;
// input_state.mouse_down[1] = nextFrameMD;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
done = 1;
@@ -225,19 +232,25 @@ int main(int argc, char *argv[]) {
} else if (event.type == SDL_MOUSEMOTION) {
input_state.mouse_x[0] = event.motion.x;
input_state.mouse_y[0] = event.motion.y;
input_state.mouse_x[1] = event.motion.x + 150;
input_state.mouse_y[1] = event.motion.y;
} else if (event.type == SDL_MOUSEBUTTONDOWN) {
if (event.button.button == SDL_BUTTON_LEFT) {
///input_state.mouse_buttons_down = 1;
input_state.mouse_down[0] = true;
input_state.mouse_down[0] = true;
nextFrameMD = true;
}
} else if (event.type == SDL_MOUSEBUTTONUP) {
if (event.button.button == SDL_BUTTON_LEFT) {
input_state.mouse_down[0] = false;
input_state.mouse_down[0] = false;
nextFrameMD = false;
//input_state.mouse_buttons_up = 1;
}
}
}
if (done) break;
input_state.mouse_last[0] = input_state.mouse_down[0];
+2
View File
@@ -31,6 +31,8 @@ typedef int64_t int64;
#ifdef _WIN32
typedef intptr_t ssize_t;
#include <tchar.h>
#define ALIGNED16(x) __declspec(align(16)) x
+148
View File
@@ -0,0 +1,148 @@
#include "base/buffer.h"
#include <stdarg.h>
#include <stdlib.h>
#include <algorithm>
#ifdef _WIN32
#include <winsock2.h>
#undef min
#undef max
#else
#include <sys/socket.h>
#endif
#include "base/logging.h"
#include "file/fd_util.h"
Buffer::Buffer() { }
Buffer::~Buffer() { }
char *Buffer::Append(ssize_t length) {
size_t old_size = data_.size();
data_.resize(old_size + length);
return &data_[0] + old_size;
}
void Buffer::Append(const std::string &str) {
char *ptr = Append(str.size());
memcpy(ptr, str.data(), str.size());
}
void Buffer::Append(const char *str) {
size_t len = strlen(str);
char *dest = Append(len);
memcpy(dest, str, len);
}
void Buffer::AppendValue(int value) {
char buf[16];
// This is slow.
sprintf(buf, "%i", value);
Append(buf);
}
void Buffer::Take(size_t length, std::string *dest) {
CHECK_LE(length, data_.size());
dest->resize(length);
memcpy(&(*dest)[0], &data_[0], length);
data_.erase(data_.begin(), data_.begin() + length);
}
int Buffer::TakeLineCRLF(std::string *dest) {
int after_next_line = OffsetToAfterNextCRLF();
if (after_next_line < 0)
return after_next_line;
else {
Take(after_next_line - 2, dest);
Skip(2); // Skip the CRLF
return after_next_line - 2;
}
}
void Buffer::Skip(size_t length) {
data_.erase(data_.begin(), data_.begin() + length);
}
int Buffer::SkipLineCRLF() {
int after_next_line = OffsetToAfterNextCRLF();
if (after_next_line < 0)
return after_next_line;
else {
Skip(after_next_line);
return after_next_line - 2;
}
}
int Buffer::OffsetToAfterNextCRLF() {
for (size_t i = 0; i < data_.size() - 1; i++) {
if (data_[i] == '\r' && data_[i + 1] == '\n') {
return i + 2;
}
}
return -1;
}
void Buffer::Printf(const char *fmt, ...) {
char buffer[512];
va_list vl;
va_start(vl, fmt);
ssize_t retval = vsnprintf(buffer, sizeof(buffer), fmt, vl);
if (retval >= (ssize_t)sizeof(buffer)) {
// Output was truncated. TODO: Do something.
FLOG("Buffer::Printf truncated output");
}
CHECK_GE(retval, 0);
va_end(vl);
char *ptr = Append(retval);
CHECK(ptr);
memcpy(ptr, buffer, retval);
}
bool Buffer::Flush(int fd) {
// Look into using send() directly.
bool success = (ssize_t)data_.size() == fd_util::WriteLine(fd, &data_[0], data_.size());
if (success) {
data_.resize(0);
}
return success;
}
bool Buffer::FlushSocket(uintptr_t sock) {
// TODO: send may need retries!
size_t sent = send(sock, &data_[0], data_.size(), 0);
// bool success = fd_util::WriteLine(fd, data_.data(), data_.size());
if (sent == data_.size()) {
data_.resize(0);
return true;
} else {
ELOG("FlushSocket failed");
return false;
}
}
void Buffer::ReadAll(int fd) {
char buf[1024];
int retval;
while ((retval = recv(fd, buf, sizeof(buf), 0)) > 0) {
char *p = Append((size_t)retval);
memcpy(p, buf, retval);
}
}
void Buffer::Read(int fd, size_t sz) {
char buf[1024];
int retval;
while ((retval = recv(fd, buf, std::min(sz, sizeof(buf)), 0)) > 0) {
char *p = Append((size_t)retval);
memcpy(p, buf, retval);
sz -= retval;
if (sz == 0)
break;
}
}
void Buffer::PeekAll(std::string *dest) {
dest->resize(data_.size());
memcpy(&(*dest)[0], &data_[0], data_.size());
}
+81
View File
@@ -0,0 +1,81 @@
#ifndef _IO_BUFFER_H
#define _IO_BUFFER_H
#include <string>
#include <vector>
#include "base/basictypes.h"
#include "base/logging.h"
// Acts as a queue. Intended to be as fast as possible for most uses.
// Does not do synchronization, must use external mutexes.
class Buffer {
public:
Buffer();
~Buffer();
// Write max [length] bytes to the returned pointer.
// Any other operation on this Buffer invalidates the pointer.
char *Append(ssize_t length);
char *Append(size_t length) { return Append((ssize_t)length); }
// These work pretty much like you'd expect.
void Append(const char *str); // str null-terminated. The null is not copied.
void Append(const std::string &str);
// Various types. Useful for varz etc. Appends a string representation of the
// value, rather than a binary representation.
void AppendValue(int value);
// Parsing Helpers
// Use for easy line skipping. If no CRLF within the buffer, returns -1.
// If parsing HTML headers, this indicates that you should probably buffer up
// more data.
int OffsetToAfterNextCRLF();
// Takers
void Take(size_t length, std::string *dest);
void TakeAll(std::string *dest) { Take(size(), dest); }
// On failure, return value < 0 and *dest is unchanged.
// Strips off the actual CRLF from the result.
int TakeLineCRLF(std::string *dest);
// Skippers
void Skip(size_t length);
// Returns -1 on failure (no CRLF within sight).
// Otherwise returns the length of the line skipped, not including CRLF. Can be 0.
int SkipLineCRLF();
// Utility functions.
void Printf(const char *fmt, ...);
// Dumps the entire buffer to the string, but keeps it around.
// Only to be used for debugging, since it might not be fast at all.
void PeekAll(std::string *dest);
// Simple I/O.
// Writes the entire buffer to the file descriptor. Also resets the
// size to zero. On failure, data remains in buffer and nothing is
// written.
bool Flush(int fd);
bool FlushSocket(uintptr_t sock); // Windows portability
void ReadAll(int fd);
void Read(int fd, size_t sz);
// Utilities. Try to avoid checking for size.
size_t size() const { return data_.size(); }
bool empty() const { return size() == 0; }
void clear() { data_.resize(0); }
private:
// TODO: Find a better internal representation, like a cord.
std::vector<char> data_;
DISALLOW_COPY_AND_ASSIGN(Buffer);
};
#endif // _IO_BUFFER_H
+78 -72
View File
@@ -1,3 +1,47 @@
#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;
}
uint32_t blackAlpha(float alpha) {
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);
}
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 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 < 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);
}
/* hsv2rgb.c
* Convert Hue Saturation Value to Red Green Blue
*
@@ -8,79 +52,41 @@
* Procedural Elements for Computer Graphics
* McGraw Hill 1985
*/
#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;
}
uint32_t blackAlpha(float alpha) {
if (alpha < 0.0f) alpha = 0.0f;
if (alpha > 1.0f) alpha = 1.0f;
return (int)(alpha*255)<<24;
}
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 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 < 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);
}
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;
float r, g, b;
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));
if (I == 0) { r = V; g = K; b = M; }
if (I == 1) { r = N; g = V; b = M; }
if (I == 2) { r = M; g = V; b = K; }
if (I == 3) { r = M; g = N; b = V; }
if (I == 4) { r = K; g = M; b = V; }
if (I == 5) { r = V; g = M; b = N; }
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);
}
}
+1
View File
@@ -4,6 +4,7 @@
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);
+14 -14
View File
@@ -13,12 +13,12 @@ __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);
}
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);
}
@@ -29,12 +29,12 @@ _ErrorContext::~_ErrorContext() {
}
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]);
}
}
}
+4 -4
View File
@@ -7,11 +7,11 @@
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__)
+7
View File
@@ -60,6 +60,13 @@ inline void Crash() {
#endif
#undef CHECK
#define CHECK(a) {if (!(a)) {FLOG("CHECK failed");}}
#define CHECK_P(a, ...) {if (!(a)) {FLOG("CHECK failed: " __VA_ARGS__);}}
#define CHECK_EQ(a, b) CHECK((a) == (b));
#define CHECK_NE(a, b) CHECK((a) != (b));
#define CHECK_GT(a, b) CHECK((a) > (b));
#define CHECK_GE(a, b) CHECK((a) >= (b));
#define CHECK_LT(a, b) CHECK((a) < (b));
#define CHECK_LE(a, b) CHECK((a) <= (b));
+26 -26
View File
@@ -14,58 +14,58 @@
class recursive_mutex {
#ifdef _WIN32
typedef CRITICAL_SECTION mutexType;
typedef CRITICAL_SECTION mutexType;
#else
typedef pthread_mutex_t mutexType;
typedef pthread_mutex_t mutexType;
#endif
public:
recursive_mutex() {
recursive_mutex() {
#ifdef _WIN32
InitializeCriticalSection(&mut_);
InitializeCriticalSection(&mut_);
#else
pthread_mutex_init(&mut_, NULL);
pthread_mutex_init(&mut_, NULL);
#endif
}
~recursive_mutex() {
}
~recursive_mutex() {
#ifdef _WIN32
DeleteCriticalSection(&mut_);
DeleteCriticalSection(&mut_);
#else
pthread_mutex_destroy(&mut_);
pthread_mutex_destroy(&mut_);
#endif
}
bool trylock() {
}
bool trylock() {
#ifdef _WIN32
return TryEnterCriticalSection(&mut_) == TRUE;
return TryEnterCriticalSection(&mut_) == TRUE;
#else
return pthread_mutex_trylock(&mut_) != EBUSY;
return pthread_mutex_trylock(&mut_) != EBUSY;
#endif
}
void lock() {
}
void lock() {
#ifdef _WIN32
EnterCriticalSection(&mut_);
EnterCriticalSection(&mut_);
#else
pthread_mutex_lock(&mut_);
pthread_mutex_lock(&mut_);
#endif
}
void unlock() {
}
void unlock() {
#ifdef _WIN32
LeaveCriticalSection(&mut_);
LeaveCriticalSection(&mut_);
#else
pthread_mutex_unlock(&mut_);
pthread_mutex_unlock(&mut_);
#endif
}
}
private:
mutexType mut_;
mutexType mut_;
};
class lock_guard {
public:
lock_guard(recursive_mutex &mtx) : mtx_(mtx) {mtx_.lock();}
~lock_guard() {mtx_.unlock();}
lock_guard(recursive_mutex &mtx) : mtx_(mtx) {mtx_.lock();}
~lock_guard() {mtx_.unlock();}
private:
recursive_mutex &mtx_;
recursive_mutex &mtx_;
};
#undef p
+12 -12
View File
@@ -4,26 +4,26 @@
template<class T>
class scoped_ptr {
public:
public:
scoped_ptr() : ptr_(0) {}
scoped_ptr(T *p) : ptr_(p) {}
~scoped_ptr() {
delete ptr_;
}
void reset(T *p) {
delete ptr_;
delete ptr_;
ptr_ = p;
}
T *release() {
T *p = ptr_;
ptr_ = 0;
return p;
}
T *operator->() { return ptr_; }
const T *operator->() const { return ptr_; }
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);
private:
scoped_ptr(const scoped_ptr<T> &other);
void operator=(const scoped_ptr<T> &other);
T *ptr_;
};
+13 -1
View File
@@ -1,9 +1,11 @@
#include <string.h>
#include "base/buffer.h"
#include "base/stringutil.h"
unsigned int parseHex(const char *_szValue)
{
DWORD Count, Value = 0;
int Count, Value = 0;
size_t Finish = strlen(_szValue);
if (Finish > 8 ) { Finish = 8; }
@@ -38,4 +40,14 @@ unsigned int parseHex(const char *_szValue)
}
}
return Value;
}
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);
}
+14 -6
View File
@@ -4,6 +4,8 @@
#include <stdio.h>
#include <string>
#include "base/basictypes.h"
#ifdef _MSC_VER
#pragma warning (disable:4996)
#endif
@@ -11,18 +13,24 @@
// Dumb wrapper around itoa, providing a buffer. Declare this on the stack.
class ITOA {
public:
char buffer[16];
const char *p(int i) {
sprintf(buffer, "%i", i);
return &buffer[0];
}
char buffer[16];
const char *p(int i) {
sprintf(buffer, "%i", i);
return &buffer[0];
}
};
// Other simple string utilities.
inline bool endsWith(const std::string &str, const std::string &what) {
return str.substr(str.size() - what.size()) == what;
return str.substr(str.size() - what.size()) == what;
}
void DataToHexString(const uint8 *data, size_t size, std::string *output);
inline void StringToHexString(const std::string &data, std::string *output) {
DataToHexString((uint8_t *)(&data[0]), data.size(), output);
}
// highly unsafe and not recommended.
unsigned int parseHex(const char* _szValue);
+18 -18
View File
@@ -18,14 +18,14 @@ __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
@@ -47,17 +47,17 @@ void time_update() {
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;
//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() {
@@ -65,16 +65,16 @@ double time_now_d() {
}
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
}
+49
View File
@@ -0,0 +1,49 @@
#pragma once
#include <vector>
#include <string>
class Listable
{
public:
virtual ~Listable() {}
virtual const char *getItem(size_t i) const = 0;
virtual size_t numItems() const = 0;
// Returns -1 for not found.
// Child classes are meant to specialize this if they have a faster way
// than brute force search.
virtual int getIndex(const char *text) {
for (size_t i = 0; i < numItems(); i++) {
if (!strcmp(getItem(i), text))
return i;
}
return -1;
}
};
class ArrayListable : public Listable
{
public:
ArrayListable(const char * const*arr, size_t count) : arr_(arr), count_(count) {}
virtual ~ArrayListable() {}
virtual const char *getItem(size_t i) const { return arr_[i]; }
virtual size_t numItems() const { return count_; }
private:
const char *const*arr_;
size_t count_;
};
class VectorListable : public Listable
{
VectorListable(const std::vector<std::string> &vec) : vec_(vec) {}
virtual ~VectorListable() {}
virtual const char *getItem(size_t i) const { return vec_[i].c_str(); }
virtual size_t numItems() const { return vec_.size(); }
private:
const std::vector<std::string> &vec_;
};
+6 -1
View File
@@ -50,7 +50,12 @@ const json_value *json_value::get(const char *child_name, json_type type) const
}
const char *json_value::getString(const char *child_name) const {
return get(child_name, JSON_STRING)->string_value;
const json_value *val = get(child_name, JSON_STRING);
if (val)
return val->string_value;
else
FLOG("String %s missing from node %s", child_name, this->name);
return 0;
}
const char *json_value::getString(const char *child_name, const char *default_value) const {
+17
View File
@@ -41,6 +41,12 @@ struct json_value
int numSiblings() const; // num siblings *after* this one only
const json_value *get(const char *child_name) const;
const json_value *get(const char *child_name, json_type type) const;
const json_value *getArray(const char *child_name) const {
return get(child_name, JSON_ARRAY);
}
const json_value *getDict(const char *child_name) const {
return get(child_name, JSON_OBJECT);
}
const char *getString(const char *child_name) const;
const char *getString(const char *child_name, const char *default_value) const;
bool getStringVector(std::vector<std::string> *vec) const;
@@ -50,6 +56,10 @@ struct json_value
int getInt(const char *child_name, int default_value) const;
bool getBool(const char *child_name) const;
bool getBool(const char *child_name, bool default_value) const;
bool hasChild(const char *child_name, json_type child_type) const {
return get(child_name, child_type) != 0;
}
private:
DISALLOW_COPY_AND_ASSIGN(json_value);
@@ -101,3 +111,10 @@ private:
DISALLOW_COPY_AND_ASSIGN(JsonReader);
};
// TODO: Make this a push/pop interface similar to JsonWriter. Maybe
// we can get to the point where reading and writing is near identical or the same code.
class JsonCursor {
public:
};
+174 -174
View File
@@ -5,270 +5,270 @@
//#define CHUNKDEBUG
ChunkFile::ChunkFile(const char *filename, bool _read) {
data=0;
data=0;
fn = filename;
fastMode=false;
numLevels=0;
read=_read;
pos=0;
didFail=false;
fastMode=false;
numLevels=0;
read=_read;
pos=0;
didFail=false;
fastMode = read ? true : false;
if (fastMode) {
if (fastMode) {
size_t size;
data = (uint8 *)VFSReadFile(filename, &size);
if (!data) {
ELOG("Chunkfile fail: %s", filename);
didFail = true;
data = (uint8 *)VFSReadFile(filename, &size);
if (!data) {
ELOG("Chunkfile fail: %s", filename);
didFail = true;
return;
}
eof = size;
return;
}
if (file.open(filename, FILE_WRITE)) {
didFail=false;
eof=file.fileSize();
} else {
didFail=true;
return;
}
if (file.open(filename, FILE_WRITE)) {
didFail=false;
eof=file.fileSize();
} else {
didFail=true;
return;
}
}
ChunkFile::~ChunkFile() {
if (fastMode && data)
delete [] data;
else
file.close();
if (fastMode && data)
delete [] data;
else
file.close();
}
int ChunkFile::readInt() {
if (pos<eof) {
/*
int temp = *(int *)(data+pos);
pos+=4;
*/
pos+=4;
if (fastMode)
return *(int *)(data+pos-4);
else
return file.readInt();
} else {
return 0;
}
if (pos<eof) {
/*
int temp = *(int *)(data+pos);
pos+=4;
*/
pos+=4;
if (fastMode)
return *(int *)(data+pos-4);
else
return file.readInt();
} else {
return 0;
}
}
void ChunkFile::writeInt(int i) {
/*
*(int *)(data+pos) = i;
pos+=4;
*/
/*
*(int *)(data+pos) = i;
pos+=4;
*/
#ifndef DEMO_VERSION //if this is missing.. heheh
file.writeInt(i);
pos+=4;
file.writeInt(i);
pos+=4;
#endif
}
//let's get into the business
bool ChunkFile::descend(uint32 id) {
id=flipID(id);
if (read) {
bool found = false;
id=flipID(id);
if (read) {
bool found = false;
//save information to restore after the next Ascend
stack[numLevels].parentStartLocation = pos;
stack[numLevels].parentEOF = eof;
//save information to restore after the next Ascend
stack[numLevels].parentStartLocation = pos;
stack[numLevels].parentEOF = eof;
ChunkInfo temp = stack[numLevels];
ChunkInfo temp = stack[numLevels];
int firstID = 0;
//let's search through children..
while(pos<eof) {
stack[numLevels].ID = readInt();
if (firstID == 0) firstID=stack[numLevels].ID|1;
stack[numLevels].length = readInt();
stack[numLevels].startLocation = pos;
int firstID = 0;
//let's search through children..
while(pos<eof) {
stack[numLevels].ID = readInt();
if (firstID == 0) firstID=stack[numLevels].ID|1;
stack[numLevels].length = readInt();
stack[numLevels].startLocation = pos;
if (stack[numLevels].ID == id)
{
found = true;
break;
} else {
seekTo(pos + stack[numLevels].length); //try next block
}
}
if (stack[numLevels].ID == id)
{
found = true;
break;
} else {
seekTo(pos + stack[numLevels].length); //try next block
}
}
//if we found nothing, return false so the caller can skip this
if (!found) {
//if we found nothing, return false so the caller can skip this
if (!found) {
#ifdef CHUNKDEBUG
ILOG("Couldn't find %c%c%c%c", id, id>>8, id>>16, id>>24);
#endif
stack[numLevels]=temp;
seekTo(stack[numLevels].parentStartLocation);
return false;
}
stack[numLevels]=temp;
seekTo(stack[numLevels].parentStartLocation);
return false;
}
//descend into it
//pos was set inside the loop above
eof = stack[numLevels].startLocation + stack[numLevels].length;
numLevels++;
//descend into it
//pos was set inside the loop above
eof = stack[numLevels].startLocation + stack[numLevels].length;
numLevels++;
#ifdef CHUNKDEBUG
ILOG("Descended into %c%c%c%c", id, id>>8, id>>16, id>>24);
#endif
return true;
} else {
return true;
} else {
#ifndef DEMO_VERSION //if this is missing.. heheh
//write a chunk id, and prepare for filling in length later
writeInt(id);
writeInt(0); //will be filled in by Ascend
stack[numLevels].startLocation=pos;
numLevels++;
return true;
//write a chunk id, and prepare for filling in length later
writeInt(id);
writeInt(0); //will be filled in by Ascend
stack[numLevels].startLocation=pos;
numLevels++;
return true;
#else
return true;
return true;
#endif
}
}
}
void ChunkFile::seekTo(int _pos) {
if (!fastMode)
file.seekBeg(_pos);
pos=_pos;
if (!fastMode)
file.seekBeg(_pos);
pos=_pos;
}
//let's ascend out
void ChunkFile::ascend() {
if (read) {
//ascend, and restore information
numLevels--;
seekTo(stack[numLevels].parentStartLocation);
eof = stack[numLevels].parentEOF;
if (read) {
//ascend, and restore information
numLevels--;
seekTo(stack[numLevels].parentStartLocation);
eof = stack[numLevels].parentEOF;
#ifdef CHUNKDEBUG
int id = stack[numLevels].ID;
ILOG("Ascended out of %c%c%c%c", id, id>>8, id>>16, id>>24);
#endif
} else {
numLevels--;
//now fill in the written length automatically
int posNow = pos;
seekTo(stack[numLevels].startLocation - 4);
writeInt(posNow-stack[numLevels].startLocation);
seekTo(posNow);
}
} else {
numLevels--;
//now fill in the written length automatically
int posNow = pos;
seekTo(stack[numLevels].startLocation - 4);
writeInt(posNow-stack[numLevels].startLocation);
seekTo(posNow);
}
}
//read a block
void ChunkFile::readData(void *what, int count) {
if (fastMode)
memcpy(what, data + pos, count);
else
file.read(what,count);
if (fastMode)
memcpy(what, data + pos, count);
else
file.read(what,count);
pos+=count;
char temp[4]; //discarded
count &= 3;
if (count) {
count=4-count;
if (!fastMode)
file.read(temp,count);
pos+=count;
}
pos+=count;
char temp[4]; //discarded
count &= 3;
if (count) {
count=4-count;
if (!fastMode)
file.read(temp,count);
pos+=count;
}
}
//write a block
void ChunkFile::writeData(const void *what, int count) {
file.write(what, count);
pos+=count;
char temp[5]={0,0,0,0,0};
count &= 3;
if (count)
{
count=4-count;
file.write(temp,count);
pos+=count;
}
file.write(what, count);
pos+=count;
char temp[5]={0,0,0,0,0};
count &= 3;
if (count)
{
count=4-count;
file.write(temp,count);
pos+=count;
}
}
void ChunkFile::writeWString(String str) {
wchar_t *text;
int len=str.length();
wchar_t *text;
int len=str.length();
#ifdef UNICODE
text = str.getPointer();
text = str.getPointer();
#else
text=new wchar_t[len+1];
str.toUnicode(text);
text=new wchar_t[len+1];
str.toUnicode(text);
#endif
writeInt(len);
writeData((char *)text,len*sizeof(wchar_t));
writeInt(len);
writeData((char *)text,len*sizeof(wchar_t));
#ifndef UNICODE
delete [] text;
delete [] text;
#endif
}
String ChunkFile::readWString() {
int len=readInt();
wchar_t *text = new wchar_t[len+1];
readData((char *)text,len*sizeof(wchar_t));
text[len]=0;
int len=readInt();
wchar_t *text = new wchar_t[len+1];
readData((char *)text,len*sizeof(wchar_t));
text[len]=0;
#ifdef UNICODE
String s(text);
delete [] text;
return s;
String s(text);
delete [] text;
return s;
#else
String temp;
temp.fromUnicode(text);
delete [] text;
return temp;
String temp;
temp.fromUnicode(text);
delete [] text;
return temp;
#endif
}
static void toUnicode(const std::string &str, uint16 *t) {
for (int i=0; i<(int)str.size(); i++) {
*t++ = str[i];
}
*t++ = '\0';
for (int i=0; i<(int)str.size(); i++) {
*t++ = str[i];
}
*t++ = '\0';
}
static std::string fromUnicode(const uint16 *src, int len) {
struct Local {
static int clamp(int i) {
return i>255?' ':i;
}
};
struct Local {
static int clamp(int i) {
return i>255?' ':i;
}
};
std::string str;
str.resize(len);
std::string str;
str.resize(len);
for (int i=0; i<len; i++) {
str[i] = Local::clamp(src[i]);
}
return str;
for (int i=0; i<len; i++) {
str[i] = Local::clamp(src[i]);
}
return str;
}
void ChunkFile::writeString(const std::string &str) {
uint16_t *text;
int len = str.size();
text=new uint16_t[len+1];
toUnicode(str, text);
writeInt(len);
writeData((char *)text,len*sizeof(uint16_t));
delete [] text;
uint16_t *text;
int len = str.size();
text=new uint16_t[len+1];
toUnicode(str, text);
writeInt(len);
writeData((char *)text,len*sizeof(uint16_t));
delete [] text;
}
std::string ChunkFile::readString() {
int len=readInt();
uint16_t *text = new uint16_t[len+1];
readData((char *)text,len*sizeof(uint16_t));
text[len]=0;
std::string temp = fromUnicode(text, len);
delete [] text;
return temp;
int len=readInt();
uint16_t *text = new uint16_t[len+1];
readData((char *)text,len*sizeof(uint16_t));
text[len]=0;
std::string temp = fromUnicode(text, len);
delete [] text;
return temp;
}
int ChunkFile::getCurrentChunkSize() {
if (numLevels)
return stack[numLevels-1].length;
else
return 0;
if (numLevels)
return stack[numLevels-1].length;
else
return 0;
}
+33 -33
View File
@@ -15,53 +15,53 @@
#include "file/easy_file.h"
inline uint32 flipID(uint32 id) {
return ((id>>24)&0xFF) | ((id>>8)&0xFF00) | ((id<<8)&0xFF0000) | ((id<<24)&0xFF000000);
return ((id>>24)&0xFF) | ((id>>8)&0xFF00) | ((id<<8)&0xFF0000) | ((id<<24)&0xFF000000);
}
class ChunkFile {
public:
ChunkFile(const char *filename, bool _read);
~ChunkFile();
ChunkFile(const char *filename, bool _read);
~ChunkFile();
bool descend(uint32 id);
void ascend();
bool descend(uint32 id);
void ascend();
int readInt();
void readInt(int &i) {i = readInt();}
void readData(void *data, int count);
String readWString();
int readInt();
void readInt(int &i) {i = readInt();}
void readData(void *data, int count);
String readWString();
void writeString(const std::string &str);
std::string readString();
void writeInt(int i);
void writeWString(String str);
void writeData(const void *data, int count);
void writeInt(int i);
void writeWString(String str);
void writeData(const void *data, int count);
int getCurrentChunkSize();
bool failed() const {return didFail;}
int getCurrentChunkSize();
bool failed() const {return didFail;}
std::string filename() const { return fn; }
private:
std::string fn;
LAMEFile file;
struct ChunkInfo {
int startLocation;
int parentStartLocation;
int parentEOF;
unsigned int ID;
int length;
};
ChunkInfo stack[8];
int numLevels;
uint8 *data;
int pos,eof;
bool fastMode;
bool read;
bool didFail;
void seekTo(int _pos);
int getPos() const {return pos;}
LAMEFile file;
struct ChunkInfo {
int startLocation;
int parentStartLocation;
int parentEOF;
unsigned int ID;
int length;
};
ChunkInfo stack[8];
int numLevels;
uint8 *data;
int pos,eof;
bool fastMode;
bool read;
bool didFail;
void seekTo(int _pos);
int getPos() const {return pos;}
};
+43 -43
View File
@@ -10,55 +10,55 @@
// An false returned means cancel;
bool OpenFileDialog(const char *title, const char *extension, std::string *filename)
{
OPENFILENAME of;
memset(&of, 0, sizeof(of));
char buffer[512] = {0};
of.lStructSize = sizeof(OPENFILENAME);
of.hInstance = 0;
of.hwndOwner = GetActiveWindow();
OPENFILENAME of;
memset(&of, 0, sizeof(of));
char buffer[512] = {0};
of.lStructSize = sizeof(OPENFILENAME);
of.hInstance = 0;
of.hwndOwner = GetActiveWindow();
// These weird strings with zeroes in them can't be dealt with using normal string
// functions, so here we go - evil hackery.
char filter[256] = "XXX files\0*.XXX\0\0";
memcpy(filter, extension, 3);
memcpy(filter + 12, extension, 3);
of.lpstrFilter = filter;
// These weird strings with zeroes in them can't be dealt with using normal string
// functions, so here we go - evil hackery.
char filter[256] = "XXX files\0*.XXX\0\0";
memcpy(filter, extension, 3);
memcpy(filter + 12, extension, 3);
of.lpstrFilter = filter;
of.lpstrDefExt = extension;
of.lpstrFile = buffer;
of.nMaxFile = 511;
of.lpstrDefExt = extension;
of.lpstrFile = buffer;
of.nMaxFile = 511;
of.Flags = OFN_FILEMUSTEXIST;
if (!GetOpenFileName(&of)) return false;
*filename = of.lpstrFile;
return true;
of.Flags = OFN_FILEMUSTEXIST;
if (!GetOpenFileName(&of)) return false;
*filename = of.lpstrFile;
return true;
}
bool SaveFileDialog(const char *title, const char *extension, std::string *filename)
{
OPENFILENAME of;
memset(&of, 0, sizeof(of));
char buffer[512] = {0};
of.lStructSize = sizeof(OPENFILENAME);
of.hInstance = 0;
of.hwndOwner = GetActiveWindow();
OPENFILENAME of;
memset(&of, 0, sizeof(of));
char buffer[512] = {0};
of.lStructSize = sizeof(OPENFILENAME);
of.hInstance = 0;
of.hwndOwner = GetActiveWindow();
// These weird strings with zeroes in them can't be dealt with using normal string
// functions, so here we go - evil hackery.
char filter[256] = "XXX files\0*.XXX\0\0";
memcpy(filter, extension, 3);
memcpy(filter + 12, extension, 3);
of.lpstrFilter = filter;
// These weird strings with zeroes in them can't be dealt with using normal string
// functions, so here we go - evil hackery.
char filter[256] = "XXX files\0*.XXX\0\0";
memcpy(filter, extension, 3);
memcpy(filter + 12, extension, 3);
of.lpstrFilter = filter;
of.lpstrDefExt = extension;
of.lpstrFile = buffer;
of.nMaxFile = 511;
of.lpstrDefExt = extension;
of.lpstrFile = buffer;
of.nMaxFile = 511;
of.Flags = OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY;
if (!GetSaveFileName(&of))
return false;
*filename = of.lpstrFile;
return true;
of.Flags = OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY;
if (!GetSaveFileName(&of))
return false;
*filename = of.lpstrFile;
return true;
}
#else
@@ -69,14 +69,14 @@ bool SaveFileDialog(const char *title, const char *extension, std::string *filen
bool OpenFileDialog(const char *title, const char *extension, std::string *filename)
{
ELOG("Asked for OpenFileDialog, not present on this platform.");
return false;
ELOG("Asked for OpenFileDialog, not present on this platform.");
return false;
}
bool SaveFileDialog(const char *title, const char *extension, std::string *filename)
{
ELOG("Asked for SaveFileDialog, not present on this platform.");
return false;
ELOG("Asked for SaveFileDialog, not present on this platform.");
return false;
}
#endif
+50 -50
View File
@@ -5,87 +5,87 @@
#include "file/easy_file.h"
LAMEFile::LAMEFile() : file_(NULL) {
isOpen = false;
isOpen = false;
}
LAMEFile::~LAMEFile() { }
bool LAMEFile::open(const char *filename, eFileMode mode) {
file_ = fopen(filename, mode == FILE_READ ? "rb" : "wb");
file_ = fopen(filename, mode == FILE_READ ? "rb" : "wb");
if (!file_) {
isOpen = false;
} else {
isOpen = true;
if (mode == FILE_READ) {
fseek(file_, 0, SEEK_END);
size_ = ftell(file_);
fseek(file_, 0, SEEK_SET);
}
}
return isOpen;
if (!file_) {
isOpen = false;
} else {
isOpen = true;
if (mode == FILE_READ) {
fseek(file_, 0, SEEK_END);
size_ = ftell(file_);
fseek(file_, 0, SEEK_SET);
}
}
return isOpen;
}
void LAMEFile::close() {
if (isOpen) {
//close the file and reset variables
fclose(file_);
file_ = NULL;
isOpen=false;
}
if (isOpen) {
//close the file and reset variables
fclose(file_);
file_ = NULL;
isOpen=false;
}
}
int LAMEFile::fileSize() {
if (!isOpen) //of course
return 0;
else
return size_;
if (!isOpen) //of course
return 0;
else
return size_;
}
std::string LAMEFile::readAll() {
std::string s;
size_t size = fileSize();
s.resize(size);
read(&s[0], size);
return s;
std::string s;
size_t size = fileSize();
s.resize(size);
read(&s[0], size);
return s;
}
int LAMEFile::write(const void *data, int size) {
if (isOpen) {
return fwrite(data, 1, size, file_); //we return the number of bytes that actually got written
} else {
return 0;
}
if (isOpen) {
return fwrite(data, 1, size, file_); //we return the number of bytes that actually got written
} else {
return 0;
}
}
int LAMEFile::read(void *data, int size) {
if (isOpen) {
return fread(data, 1, size, file_);
} else {
return 0;
}
if (isOpen) {
return fread(data, 1, size, file_);
} else {
return 0;
}
}
int LAMEFile::readInt() {
int temp;
if (read(&temp, sizeof(int)))
return temp;
else
return 0;
int temp;
if (read(&temp, sizeof(int)))
return temp;
else
return 0;
}
void LAMEFile::writeInt(int i) {
write(&i, sizeof(int));
write(&i, sizeof(int));
}
char LAMEFile::readChar() {
char temp;
if (read(&temp, sizeof(char)))
return temp;
else
return 0;
char temp;
if (read(&temp, sizeof(char)))
return temp;
else
return 0;
}
void LAMEFile::writeChar(char i) {
write(&i,sizeof(char));
write(&i,sizeof(char));
}
+32 -32
View File
@@ -11,48 +11,48 @@
// Raw file paths, does not go through VFS.
enum eFileMode {
FILE_READ=5,
FILE_WRITE=6
FILE_READ=5,
FILE_WRITE=6
};
// TODO: Rename.
class LAMEFile {
public:
LAMEFile();
virtual ~LAMEFile();
LAMEFile();
virtual ~LAMEFile();
bool open(const char *filename, eFileMode mode);
bool open(std::string filename, eFileMode mode) {
return open(filename.c_str(), mode);
}
void close();
bool open(const char *filename, eFileMode mode);
bool open(std::string filename, eFileMode mode) {
return open(filename.c_str(), mode);
}
void close();
void writeInt(int i);
void writeChar(char i);
int write(const void *data, int size);
void write(const std::string &str) {
write((void *)str.data(), str.size());
}
void writeInt(int i);
void writeChar(char i);
int write(const void *data, int size);
void write(const std::string &str) {
write((void *)str.data(), str.size());
}
int readInt();
char readChar();
int read(void *data, int size);
int readInt();
char readChar();
int read(void *data, int size);
std::string readAll();
std::string readAll();
int fileSize();
int fileSize();
void seekBeg(int pos) {
if (isOpen) fseek(file_,pos,SEEK_SET);
}
void seekEnd(int pos) {
if (isOpen) fseek(file_,pos,SEEK_END);
}
void seekCurrent(int pos) {
if (isOpen) fseek(file_,pos,SEEK_CUR);
}
void seekBeg(int pos) {
if (isOpen) fseek(file_,pos,SEEK_SET);
}
void seekEnd(int pos) {
if (isOpen) fseek(file_,pos,SEEK_END);
}
void seekCurrent(int pos) {
if (isOpen) fseek(file_,pos,SEEK_CUR);
}
private:
FILE *file_;
bool isOpen;
int size_;
FILE *file_;
bool isOpen;
int size_;
};
+121
View File
@@ -0,0 +1,121 @@
#include "file/fd_util.h"
#include <errno.h>
#include <math.h>
#include <stdio.h>
#ifndef _WIN32
#include <unistd.h>
#else
#include <io.h>
#include <winsock2.h>
#endif
#include <fcntl.h>
#include "base/logging.h"
namespace fd_util {
// Slow as hell and should only be used for prototyping.
// Reads from a socket, up to an '\n'. This means that if the line ends
// with '\r', the '\r' will be returned.
ssize_t ReadLine(int fd, char *vptr, size_t buf_size) {
char *buffer = vptr;
size_t n;
for (n = 1; n < buf_size; n++) {
char c;
ssize_t rc;
if ((rc = read(fd, &c, 1)) == 1) {
*buffer++ = c;
if (c == '\n')
break;
}
else if (rc == 0) {
if (n == 1)
return 0;
else
break;
}
else {
if (errno == EINTR)
continue;
FLOG("Error in Readline()");
}
}
*buffer = 0;
return n;
}
// Misnamed, it just writes raw data in a retry loop.
ssize_t WriteLine(int fd, const char *vptr, size_t n) {
const char *buffer = vptr;
size_t nleft = n;
while (nleft > 0) {
ssize_t nwritten;
if ((nwritten = write(fd, buffer, nleft)) <= 0) {
if (errno == EINTR)
nwritten = 0;
else
FLOG("Error in Writeline()");
}
nleft -= nwritten;
buffer += nwritten;
}
return n;
}
ssize_t WriteLine(int fd, const char *buffer) {
return WriteLine(fd, buffer, strlen(buffer));
}
ssize_t Write(int fd, const std::string &str) {
return WriteLine(fd, str.c_str(), str.size());
}
bool WaitUntilReady(int fd, double timeout) {
struct timeval tv;
tv.tv_sec = floor(timeout);
tv.tv_usec = (timeout - floor(timeout)) * 1000000.0;
fd_set fds;
FD_ZERO(&fds);
FD_SET(fd, &fds);
// First argument to select is the highest socket in the set + 1.
int rval = select(fd + 1, &fds, NULL, NULL, &tv);
if (rval < 0) {
// Error calling select.
return false;
} else if (rval == 0) {
// Timeout.
return false;
} else {
// Socket is ready.
return true;
}
}
void SetNonBlocking(int sock, bool non_blocking) {
#ifndef _WIN32
int opts = fcntl(sock, F_GETFL);
if (opts < 0) {
perror("fcntl(F_GETFL)");
exit(EXIT_FAILURE);
}
if (non_blocking) {
opts = (opts | O_NONBLOCK);
} else {
opts = (opts & ~O_NONBLOCK);
}
if (fcntl(sock, F_SETFL, opts) < 0) {
perror("fcntl(F_SETFL)");
exit(EXIT_FAILURE);
}
#else
WLOG("NonBlocking mode not supported on Win32");
#endif
}
} // fd_util
+27
View File
@@ -0,0 +1,27 @@
#ifndef _FD_UTIL
#define _FD_UTIL
#include <string.h>
#include <string>
#include "base/basictypes.h"
namespace fd_util {
// Slow as hell and should only be used for prototyping.
ssize_t ReadLine(int fd, char *buffer, size_t buf_size);
// Decently fast.
ssize_t WriteLine(int fd, const char *buffer, size_t buf_size);
ssize_t WriteLine(int fd, const char *buffer);
ssize_t Write(int fd, const std::string &str);
// Returns true if the fd became ready, false if it didn't or
// if there was another error.
bool WaitUntilReady(int fd, double timeout);
void SetNonBlocking(int fd, bool non_blocking);
} // fd_util
#endif // _FD_UTIL
+79 -79
View File
@@ -14,47 +14,47 @@
bool writeStringToFile(bool text_file, const std::string &str, const char *filename)
{
FILE *f = fopen(filename, text_file ? "w" : "wb");
if (!f)
return false;
size_t len = str.size();
if (len != fwrite(str.data(), 1, str.size(), f))
{
fclose(f);
return false;
}
fclose(f);
return true;
FILE *f = fopen(filename, text_file ? "w" : "wb");
if (!f)
return false;
size_t len = str.size();
if (len != fwrite(str.data(), 1, str.size(), f))
{
fclose(f);
return false;
}
fclose(f);
return true;
}
uint64_t GetSize(FILE *f)
{
// can't use off_t here because it can be 32-bit
uint64_t pos = ftell(f);
if (fseek(f, 0, SEEK_END) != 0) {
return 0;
}
uint64_t size = ftell(f);
// can't use off_t here because it can be 32-bit
uint64_t pos = ftell(f);
if (fseek(f, 0, SEEK_END) != 0) {
return 0;
}
uint64_t size = ftell(f);
// Reset the seek position to where it was when we started.
if ((size != pos) && (fseek(f, pos, SEEK_SET) != 0)) {
if ((size != pos) && (fseek(f, pos, SEEK_SET) != 0)) {
// Should error here
return 0;
}
return size;
return 0;
}
return size;
}
bool ReadFileToString(bool text_file, const char *filename, std::string &str)
{
FILE *f = fopen(filename, text_file ? "r" : "rb");
if (!f)
return false;
size_t len = (size_t)GetSize(f);
char *buf = new char[len + 1];
buf[fread(buf, 1, len, f)] = 0;
str = std::string(buf, len);
fclose(f);
delete [] buf;
return true;
FILE *f = fopen(filename, text_file ? "r" : "rb");
if (!f)
return false;
size_t len = (size_t)GetSize(f);
char *buf = new char[len + 1];
buf[fread(buf, 1, len, f)] = 0;
str = std::string(buf, len);
fclose(f);
delete [] buf;
return true;
}
#define DIR_SEP "/"
@@ -63,77 +63,77 @@ bool ReadFileToString(bool text_file, const char *filename, std::string &str)
size_t getFilesInDir(const char *directory, std::vector<std::string> *files)
{
size_t foundEntries = 0;
size_t foundEntries = 0;
#ifdef _WIN32
// Find the first file in the directory.
WIN32_FIND_DATA ffd;
// Find the first file in the directory.
WIN32_FIND_DATA ffd;
#ifdef UNICODE
HANDLE hFind = FindFirstFile((std::wstring(directory) + "\\*").c_str(), &ffd);
HANDLE hFind = FindFirstFile((std::wstring(directory) + "\\*").c_str(), &ffd);
#else
HANDLE hFind = FindFirstFile((std::string(directory) + "\\*").c_str(), &ffd);
HANDLE hFind = FindFirstFile((std::string(directory) + "\\*").c_str(), &ffd);
#endif
if (hFind == INVALID_HANDLE_VALUE)
{
FindClose(hFind);
return foundEntries;
}
// windows loop
do
{
const std::string virtualName(ffd.cFileName);
if (hFind == INVALID_HANDLE_VALUE)
{
FindClose(hFind);
return foundEntries;
}
// windows loop
do
{
const std::string virtualName(ffd.cFileName);
#else
struct dirent dirent, *result = NULL;
struct dirent dirent, *result = NULL;
DIR *dirp = opendir(directory);
if (!dirp)
return 0;
DIR *dirp = opendir(directory);
if (!dirp)
return 0;
// non windows loop
while (!readdir_r(dirp, &dirent, &result) && result)
{
const std::string virtualName(result->d_name);
// non windows loop
while (!readdir_r(dirp, &dirent, &result) && result)
{
const std::string virtualName(result->d_name);
#endif
// check for "." and ".."
if (((virtualName[0] == '.') && (virtualName[1] == '\0')) ||
((virtualName[0] == '.') && (virtualName[1] == '.') &&
(virtualName[2] == '\0')))
continue;
// check for "." and ".."
if (((virtualName[0] == '.') && (virtualName[1] == '\0')) ||
((virtualName[0] == '.') && (virtualName[1] == '.') &&
(virtualName[2] == '\0')))
continue;
files->push_back(std::string(directory) + virtualName);
files->push_back(std::string(directory) + virtualName);
#ifdef _WIN32
} while (FindNextFile(hFind, &ffd) != 0);
FindClose(hFind);
} while (FindNextFile(hFind, &ffd) != 0);
FindClose(hFind);
#else
}
}
closedir(dirp);
#endif
return foundEntries;
return foundEntries;
}
void deleteFile(const char *file)
{
#ifdef _WIN32
if (!DeleteFile(file)) {
ELOG("Error deleting %s: %i", file, GetLastError());
}
if (!DeleteFile(file)) {
ELOG("Error deleting %s: %i", file, GetLastError());
}
#else
int err = unlink(file);
if (err) {
ELOG("Error unlinking %s: %i", file, err);
}
int err = unlink(file);
if (err) {
ELOG("Error unlinking %s: %i", file, err);
}
#endif
}
#endif
std::string getDir(const std::string &path)
{
int n = path.size() - 1;
while (n >= 0 && path[n] != '\\' && path[n] != '/')
n--;
std::string cutpath = path.substr(0, n);
for (size_t i = 0; i < cutpath.size(); i++)
{
if (cutpath[i] == '\\') cutpath[i] = '/';
}
return cutpath;
int n = path.size() - 1;
while (n >= 0 && path[n] != '\\' && path[n] != '/')
n--;
std::string cutpath = path.substr(0, n);
for (size_t i = 0; i < cutpath.size(); i++)
{
if (cutpath[i] == '\\') cutpath[i] = '/';
}
return cutpath;
}
+11 -11
View File
@@ -83,13 +83,13 @@ uint8_t *ZipAssetReader::ReadAsset(const char *path, size_t *size) {
#endif
uint8_t *DirectoryAssetReader::ReadAsset(const char *path, size_t *size) {
char new_path[256] = {0};
// Check if it already contains the path
char new_path[256] = {0};
// Check if it already contains the path
if (strlen(path) > strlen(path_) && 0 == memcmp(path, path_, strlen(path_))) {
}
else {
strcpy(new_path, path_);
}
}
else {
strcpy(new_path, path_);
}
strcat(new_path, path);
// ILOG("New path: %s", new_path);
return ReadLocalFile(new_path, size);
@@ -125,11 +125,11 @@ uint8_t *VFSReadFile(const char *filename, size_t *size) {
if (0 == memcmp(filename, entries[i].prefix, prefix_len)) {
// ILOG("Prefix match: %s (%s) -> %s", entries[i].prefix, filename, filename + prefix_len);
uint8_t *data = entries[i].reader->ReadAsset(filename + prefix_len, size);
if (data)
return data;
else
continue;
// Else try the other registered file systems.
if (data)
return data;
else
continue;
// Else try the other registered file systems.
}
}
ELOG("Missing filesystem for %s", filename);
+10 -10
View File
@@ -23,13 +23,13 @@ void glCheckzor(const char *file, int line) {
#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) {
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;
@@ -41,8 +41,8 @@ void log_callback(GLenum source, GLenum type,
break;
default:
break;
}
switch (type) {
}
switch (type) {
case GL_DEBUG_TYPE_ERROR_ARB:
case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB:
ELOG("%s: %s", src, message);
@@ -50,7 +50,7 @@ void log_callback(GLenum source, GLenum type,
default:
ILOG("%s: %s", src, message);
break;
}
}
}
#endif
#endif
+1 -1
View File
@@ -28,7 +28,7 @@ void gl_lost() {
return;
}
for (std::list<GfxResourceHolder *>::iterator iter = holders->begin();
iter != holders->end(); ++iter) {
iter != holders->end(); ++iter) {
(*iter)->GLLost();
}
}
+63 -63
View File
@@ -68,34 +68,34 @@ static void SetTextureParameters(int zim_flags) {
}
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);
#else
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;
}
#ifdef ANDROID
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);
#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;
}
filename_ = filename;
@@ -123,27 +123,27 @@ bool Texture::Load(const char *filename) {
const char *name = fn;
if (zim && 0==memcmp(name, "Media/textures/", strlen("Media/textures"))) name += strlen("Media/textures/");
len = strlen(name);
#ifndef ANDROID
#ifndef ANDROID
if (!strcmp("png", &name[len-3]) ||
!strcmp("PNG", &name[len-3])) {
if (!LoadPNG(fn)) {
LoadXOR();
return false;
} else {
return true;
}
!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;
#endif
if (!strcmp("zim", &name[len-3])) {
if (!LoadZIM(name)) {
LoadXOR();
return false;
} else {
return true;
}
}
}
LoadXOR();
return false;
LoadXOR();
return false;
}
#ifndef ANDROID
@@ -157,7 +157,7 @@ bool Texture::LoadPNG(const char *filename) {
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);
GL_RGBA, GL_UNSIGNED_BYTE, image_data);
glGenerateMipmap(GL_TEXTURE_2D);
GL_CHECK();
free(image_data);
@@ -166,22 +166,22 @@ bool Texture::LoadPNG(const char *filename) {
#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;
}
}
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_);
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);
GL_RGBA, GL_UNSIGNED_BYTE, buf);
glGenerateMipmap(GL_TEXTURE_2D);
GL_CHECK();
delete [] buf;
@@ -198,7 +198,7 @@ uint8_t *ETC1ToRGBA(uint8_t *etc1, int width, int height) {
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);
rgba + (y * width + x) * 4, width, 255);
}
}
return rgba;
@@ -256,7 +256,7 @@ bool Texture::LoadZIM(const char *filename) {
#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]);
GL_RGBA, GL_UNSIGNED_BYTE, image_data[l]);
#endif
}
GL_CHECK();
@@ -266,7 +266,7 @@ bool Texture::LoadZIM(const char *filename) {
} 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]);
colors, data_type, image_data[l]);
}
if (num_levels == 1 && (flags & ZIM_GEN_MIPS)) {
glGenerateMipmap(GL_TEXTURE_2D);
@@ -282,8 +282,8 @@ bool Texture::LoadZIM(const char *filename) {
void Texture::Bind(int stage) {
GL_CHECK();
if (stage != -1)
glActiveTexture(GL_TEXTURE0 + stage);
if (stage != -1)
glActiveTexture(GL_TEXTURE0 + stage);
glBindTexture(GL_TEXTURE_2D, id_);
GL_CHECK();
}
+5 -5
View File
@@ -9,7 +9,7 @@
#include "gfx/gl_lost_manager.h"
class Texture : public GfxResourceHolder {
public:
public:
Texture();
~Texture();
@@ -18,10 +18,10 @@ class Texture : public GfxResourceHolder {
bool LoadPNG(const char *filename);
#endif
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.
// If filename begins with "gen:", will defer to texture_gen.cpp/h.
bool Load(const char *filename);
void Bind(int stage = -1);
@@ -35,10 +35,10 @@ class Texture : public GfxResourceHolder {
virtual void GLLost();
std::string filename() const { return filename_; }
private:
private:
std::string filename_;
#ifdef METRO
ID3D11Texture2D *tex_;
ID3D11Texture2D *tex_;
#endif
unsigned int id_;
int width_, height_;
+36 -36
View File
@@ -12,42 +12,42 @@
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);
bool mip = false;
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;
}
}
}
bool mip = false;
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;
}
+148 -117
View File
@@ -10,7 +10,10 @@
#endif
#endif
#include <algorithm>
#include <cmath>
#include "base/display.h"
#include "base/logging.h"
#include "math/math_util.h"
#include "gfx_es2/draw_buffer.h"
@@ -38,7 +41,7 @@ void DrawBuffer::Begin(DrawBufferMode dbmode) {
}
void DrawBuffer::End() {
// Currently does nothing, but call it!
// Currently does nothing, but call it!
}
void DrawBuffer::Flush(const GLSLProgram *program, bool set_blend_state) {
@@ -46,10 +49,10 @@ void DrawBuffer::Flush(const GLSLProgram *program, bool set_blend_state) {
return;
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
if (set_blend_state) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
if (set_blend_state) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
glUniform1i(program->sampler0, 0);
glEnableVertexAttribArray(program->a_position);
glEnableVertexAttribArray(program->a_color);
@@ -57,7 +60,7 @@ void DrawBuffer::Flush(const GLSLProgram *program, bool set_blend_state) {
glEnableVertexAttribArray(program->a_texcoord0);
GL_CHECK();
glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), &verts_[0].x);
glVertexAttribPointer(program->a_color, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), &verts_[0].r);
glVertexAttribPointer(program->a_color, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), &verts_[0].rgba);
if (program->a_texcoord0 != -1)
glVertexAttribPointer(program->a_texcoord0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), &verts_[0].u);
glDrawArrays(mode_ == DBMODE_LINES ? GL_LINES : GL_TRIANGLES, 0, count_);
@@ -68,54 +71,50 @@ void DrawBuffer::Flush(const GLSLProgram *program, bool set_blend_state) {
glDisableVertexAttribArray(program->a_texcoord0);
GL_CHECK();
count_ = 0;
count_ = 0;
}
void DrawBuffer::V(float x, float y, float z, uint32 color, float u, float v) {
Vertex *vert = &verts_[count_++];
Vertex *vert = &verts_[count_++];
vert->x = x;
vert->y = y;
vert->z = z;
// todo: speedup rgba here
vert->r = color & 0xFF;
vert->g = (color >> 8) & 0xFF;
vert->b = (color >> 16) & 0xFF;
vert->a = (color >> 24) & 0xFF;
vert->rgba = color;
vert->u = u;
vert->v = v;
}
void DrawBuffer::Rect(float x, float y, float w, float h, uint32 color, int align) {
DoAlign(align, &x, &y, w, h);
DoAlign(align, &x, &y, &w, &h);
RectVGradient(x, y, w, h, color, color);
}
void DrawBuffer::RectVGradient(float x, float y, float w, float h, uint32 colorTop, uint32 colorBottom) {
V(x, y, 0, colorTop, 0, 0);
V(x + w, y, 0, colorTop, 1, 0);
V(x + w, y + h, 0, colorBottom, 1, 1);
V(x, y, 0, colorTop, 0, 0);
V(x + w, y + h, 0, colorBottom, 1, 1);
V(x, y + h, 0, colorBottom, 0, 1);
V(x, y, 0, colorTop, 0, 0);
V(x + w, y, 0, colorTop, 1, 0);
V(x + w, y + h, 0, colorBottom, 1, 1);
V(x, y, 0, colorTop, 0, 0);
V(x + w, y + h, 0, colorBottom, 1, 1);
V(x, y + h, 0, colorBottom, 0, 1);
}
void DrawBuffer::MultiVGradient(float x, float y, float w, float h, GradientStop *stops, int numStops) {
for (int i = 0; i < numStops - 1; i++) {
float t0 = stops[i].t, t1 = stops[i+1].t;
uint32_t c0 = stops[i].t, c1 = stops[i+1].t;
RectVGradient(x, y + h * t0, w, h * (t1 - t0), c0, c1);
}
for (int i = 0; i < numStops - 1; i++) {
float t0 = stops[i].t, t1 = stops[i+1].t;
uint32_t c0 = stops[i].t, c1 = stops[i+1].t;
RectVGradient(x, y + h * t0, w, h * (t1 - t0), c0, c1);
}
}
void DrawBuffer::Rect(float x, float y, float w, float h,
float u, float v, float uw, float uh,
uint32 color) {
V(x, y, 0, color, u, v);
V(x + w, y, 0, color, u + uw, v);
V(x + w, y + h, 0, color, u + uw, v + uh);
V(x, y, 0, color, u, v);
V(x + w, y + h, 0, color, u + uw, v + uh);
V(x, y + h, 0, color, u, v + uh);
float u, float v, float uw, float uh,
uint32 color) {
V(x, y, 0, color, u, v);
V(x + w, y, 0, color, u + uw, v);
V(x + w, y + h, 0, color, u + uw, v + uh);
V(x, y, 0, color, u, v);
V(x + w, y + h, 0, color, u + uw, v + uh);
V(x, y + h, 0, color, u, v + uh);
}
void DrawBuffer::MeasureImage(int atlas_image, float *w, float *h) {
@@ -128,10 +127,10 @@ void DrawBuffer::DrawImage(int atlas_image, float x, float y, float scale, Color
const AtlasImage &image = atlas->images[atlas_image];
float w = (float)image.w * scale;
float h = (float)image.h * scale;
if (align & ALIGN_HCENTER) x -= w / 2;
if (align & ALIGN_RIGHT) x -= w;
if (align & ALIGN_VCENTER) y -= h / 2;
if (align & ALIGN_BOTTOM) y -= h;
if (align & ALIGN_HCENTER) x -= w / 2;
if (align & ALIGN_RIGHT) x -= w;
if (align & ALIGN_VCENTER) y -= h / 2;
if (align & ALIGN_BOTTOM) y -= h;
DrawImageStretch(atlas_image, x, y, x + w, y + h, color);
}
@@ -145,76 +144,74 @@ void DrawBuffer::DrawImageStretch(int atlas_image, float x1, float y1, float x2,
V(x1, y2, color, image.u1, image.v2);
}
inline void rot(float *v, float angle, float xc, float yc) {
v[0]-=xc;
v[1]-=yc;
inline void rot(float *v, float angle, float xc,float yc)
{
v[0]-=xc;
v[1]-=yc;
float ca=cosf(angle),sa=sinf(angle);
float ca=cosf(angle),sa=sinf(angle);
float t0 = v[0] * ca + v[1] * -sa;
float t1 = v[0] * sa + v[1] * ca;
float t0 = v[0] * ca + v[1] * -sa;
float t1 = v[0] * sa + v[1] * ca;
v[0] = t0 + xc;
v[1] = t1 + yc;
v[0] = t0 + xc;
v[1] = t1 + yc;
}
void DrawBuffer::DrawImageRotated(int atlas_image, float x, float y, float scale, float angle, Color color) {
const AtlasImage &image = atlas->images[atlas_image];
float w = (float)image.w * scale;
float h = (float)image.h * scale;
float x1 = x - w / 2;
float x2 = x + w / 2;
float y1 = y - h / 2;
float y2 = y + h / 2;
float v[6][2] = {
{x1, y1},
{x2, y1},
{x2, y2},
{x1, y1},
{x2, y2},
{x1, y2},
};
const float uv[6][2] = {
{image.u1, image.v1},
{image.u2, image.v1},
{image.u2, image.v2},
{image.u1, image.v1},
{image.u2, image.v2},
{image.u1, image.v2},
};
for (int i = 0; i < 6; i++) {
rot(v[i], angle, x, y);
V(v[i][0], v[i][1], 0, color, uv[i][0], uv[i][1]);
}
const AtlasImage &image = atlas->images[atlas_image];
float w = (float)image.w * scale;
float h = (float)image.h * scale;
float x1 = x - w / 2;
float x2 = x + w / 2;
float y1 = y - h / 2;
float y2 = y + h / 2;
float v[6][2] = {
{x1, y1},
{x2, y1},
{x2, y2},
{x1, y1},
{x2, y2},
{x1, y2},
};
const float uv[6][2] = {
{image.u1, image.v1},
{image.u2, image.v1},
{image.u2, image.v2},
{image.u1, image.v1},
{image.u2, image.v2},
{image.u1, image.v2},
};
for (int i = 0; i < 6; i++) {
rot(v[i], angle, x, y);
V(v[i][0], v[i][1], 0, color, uv[i][0], uv[i][1]);
}
}
// TODO: add arc support
void DrawBuffer::Circle(float xc, float yc, float radius, float thickness, int segments, float startAngle, uint32 color, float u_mul) {
float angleDelta = PI * 2 / segments;
float uDelta = 1.0f / segments;
float t2 = thickness / 2.0f;
float r1 = radius + t2;
float r2 = radius - t2;
for (int i = 0; i < segments + 1; i++) {
float angle1 = i * angleDelta;
float angle2 = (i + 1) * angleDelta;
float u1 = u_mul * i * uDelta;
float u2 = u_mul * (i + 1) * uDelta;
// TODO: get rid of one pair of cos/sin per loop, can reuse from last iteration
float c1 = cosf(angle1), s1 = sinf(angle1), c2 = cosf(angle2), s2 = sinf(angle2);
const float x[4] = {c1 * r1 + xc, c2 * r1 + xc, c1 * r2 + xc, c2 * r2 + xc};
const float y[4] = {s1 * r1 + yc, s2 * r1 + yc, s1 * r2 + yc, s2 * r2 + yc};
V(x[0], y[0], color, u1, 0);
V(x[1], y[1], color, u2, 0);
V(x[2], y[2], color, u1, 1);
V(x[1], y[1], color, u2, 0);
V(x[3], y[3], color, u2, 1);
V(x[2], y[2], color, u1, 1);
}
float angleDelta = PI * 2 / segments;
float uDelta = 1.0f / segments;
float t2 = thickness / 2.0f;
float r1 = radius + t2;
float r2 = radius - t2;
for (int i = 0; i < segments + 1; i++) {
float angle1 = i * angleDelta;
float angle2 = (i + 1) * angleDelta;
float u1 = u_mul * i * uDelta;
float u2 = u_mul * (i + 1) * uDelta;
// TODO: get rid of one pair of cos/sin per loop, can reuse from last iteration
float c1 = cosf(angle1), s1 = sinf(angle1), c2 = cosf(angle2), s2 = sinf(angle2);
const float x[4] = {c1 * r1 + xc, c2 * r1 + xc, c1 * r2 + xc, c2 * r2 + xc};
const float y[4] = {s1 * r1 + yc, s2 * r1 + yc, s1 * r2 + yc, s2 * r2 + yc};
V(x[0], y[0], color, u1, 0);
V(x[1], y[1], color, u2, 0);
V(x[2], y[2], color, u1, 1);
V(x[1], y[1], color, u2, 0);
V(x[3], y[3], color, u2, 1);
V(x[2], y[2], color, u1, 1);
}
}
void DrawBuffer::DrawTexRect(float x1, float y1, float x2, float y2, float u1, float v1, float u2, float v2, Color color) {
@@ -269,14 +266,14 @@ void DrawBuffer::MeasureText(int font, const char *text, float *w, float *h) {
const AtlasFont &atlasfont = *atlas->fonts[font];
unsigned char cval;
float wacc = 0, maxh = 0;
int lines = 1;
int lines = 1;
while ((cval = *text++) != '\0') {
if (cval < 32) continue;
if (cval > 127) continue;
if (cval == '\n') {
wacc = 0;
lines++;
}
if (cval == '\n') {
wacc = 0;
lines++;
}
AtlasChar c = atlasfont.chars[cval - 32];
wacc += c.wx * fontscalex;
}
@@ -285,27 +282,38 @@ void DrawBuffer::MeasureText(int font, const char *text, float *w, float *h) {
}
void DrawBuffer::DrawTextShadow(int font, const char *text, float x, float y, Color color, int flags) {
uint32_t alpha = (color >> 1) & 0xFF000000;
uint32_t alpha = (color >> 1) & 0xFF000000;
DrawText(font, text, x + 2, y + 2, alpha, flags);
DrawText(font, text, x, y, color, flags);
}
void DrawBuffer::DoAlign(int align, float *x, float *y, float w, float h) {
if (align & ALIGN_HCENTER) *x -= w / 2;
if (align & ALIGN_RIGHT) *x -= w;
if (align & ALIGN_VCENTER) *y -= h / 2;
if (align & ALIGN_BOTTOM) *y -= h;
void DrawBuffer::DoAlign(int flags, float *x, float *y, float *w, float *h) {
if (flags & ALIGN_HCENTER) *x -= *w / 2;
if (flags & ALIGN_RIGHT) *x -= *w;
if (flags & ALIGN_VCENTER) *y -= *h / 2;
if (flags & ALIGN_BOTTOM) *y -= *h;
if (flags & (ROTATE_90DEG_LEFT | ROTATE_90DEG_RIGHT)) {
std::swap(*w, *h);
std::swap(*x, *y);
}
}
// ROTATE_* doesn't yet work right.
void DrawBuffer::DrawText(int font, const char *text, float x, float y, Color color, int flags) {
const AtlasFont &atlasfont = *atlas->fonts[font];
unsigned char cval;
float w, h;
MeasureText(font, text, &w, &h);
if (flags) {
DoAlign(flags, &x, &y, w, h);
DoAlign(flags, &x, &y, &w, &h);
}
y+=atlasfont.ascend*fontscaley;
if (flags & ROTATE_90DEG_LEFT) {
x -= atlasfont.ascend*fontscaley;
// y += h;
}
else
y += atlasfont.ascend*fontscaley;
float sx = x;
while ((cval = *text++) != '\0') {
if (cval == '\n') {
@@ -316,23 +324,46 @@ void DrawBuffer::DrawText(int font, const char *text, float x, float y, Color co
if (cval < 32) continue;
if (cval > 127) continue;
AtlasChar c = atlasfont.chars[cval - 32];
float cx1 = x + c.ox * fontscalex;
float cy1 = y + c.oy * fontscaley;
float cx2 = x + (c.ox + c.pw) * fontscalex;
float cy2 = y + (c.oy + c.ph) * fontscaley;
float cx1, cy1, cx2, cy2;
if (flags & ROTATE_90DEG_LEFT) {
cy1 = y - c.ox * fontscalex;
cx1 = x + c.oy * fontscaley;
cy2 = y - (c.ox + c.pw) * fontscalex;
cx2 = x + (c.oy + c.ph) * fontscaley;
} else {
cx1 = x + c.ox * fontscalex;
cy1 = y + c.oy * fontscaley;
cx2 = x + (c.ox + c.pw) * fontscalex;
cy2 = y + (c.oy + c.ph) * fontscaley;
}
V(cx1, cy1, color, c.sx, c.sy);
V(cx2, cy1, color, c.ex, c.sy);
V(cx2, cy2, color, c.ex, c.ey);
V(cx1, cy1, color, c.sx, c.sy);
V(cx2, cy2, color, c.ex, c.ey);
V(cx1, cy2, color, c.sx, c.ey);
x += c.wx * fontscalex;
if (flags & ROTATE_90DEG_LEFT)
y -= c.wx * fontscalex;
else
x += c.wx * fontscalex;
}
}
void DrawBuffer::EnableBlend(bool enable) {
if (enable)
glEnable(GL_BLEND);
else
glDisable(GL_BLEND);
if (enable)
glEnable(GL_BLEND);
else
glDisable(GL_BLEND);
}
void DrawBuffer::SetClipRect(float x, float y, float w, float h)
{
// Sigh, OpenGL is upside down.
glScissor(x, g_yres - y, w, h);
glEnable(GL_SCISSOR_TEST);
}
void DrawBuffer::NoClip()
{
glDisable(GL_SCISSOR_TEST);
}
+33 -21
View File
@@ -9,17 +9,22 @@ struct Atlas;
enum {
ALIGN_LEFT = 0,
ALIGN_RIGHT = 16,
ALIGN_TOP = 0,
ALIGN_BOTTOM = 1,
ALIGN_RIGHT = 16,
ALIGN_TOP = 0,
ALIGN_BOTTOM = 1,
ALIGN_HCENTER = 4,
ALIGN_VCENTER = 8,
ALIGN_VBASELINE = 32, // text only, possibly not yet working
ALIGN_VBASELINE = 32, // text only, possibly not yet working
ALIGN_TOPLEFT = ALIGN_TOP | ALIGN_LEFT,
ALIGN_TOPRIGHT = ALIGN_TOP | ALIGN_RIGHT,
ALIGN_BOTTOMLEFT = ALIGN_BOTTOM | ALIGN_LEFT,
ALIGN_BOTTOMRIGHT = ALIGN_BOTTOM | ALIGN_RIGHT,
ALIGN_TOPLEFT = ALIGN_TOP | ALIGN_LEFT,
ALIGN_TOPRIGHT = ALIGN_TOP | ALIGN_RIGHT,
ALIGN_BOTTOMLEFT = ALIGN_BOTTOM | ALIGN_LEFT,
ALIGN_BOTTOMRIGHT = ALIGN_BOTTOM | ALIGN_RIGHT,
// Only for text drawing
ROTATE_90DEG_LEFT = 256,
ROTATE_90DEG_RIGHT = 512,
ROTATE_180DEG = 1024,
};
struct GLSLProgram;
@@ -31,12 +36,12 @@ enum DrawBufferMode {
struct GradientStop
{
float t;
uint32_t color;
float t;
uint32_t color;
};
class DrawBuffer {
public:
public:
DrawBuffer();
~DrawBuffer();
@@ -47,21 +52,21 @@ class DrawBuffer {
void Flush(const GLSLProgram *program, bool set_blend_state=true);
void Rect(float x, float y, float w, float h, uint32 color, int align = ALIGN_TOPLEFT);
void RectVGradient(float x, float y, float w, float h, uint32 colorTop, uint32 colorBottom);
void RectVGradient(float x, float y, float w, float h, uint32 colorTop, uint32 colorBottom);
void MultiVGradient(float x, float y, float w, float h, GradientStop *stops, int numStops);
void MultiVGradient(float x, float y, float w, float h, GradientStop *stops, int numStops);
void RectCenter(float x, float y, float w, float h, uint32 color) {
Rect(x - w/2, y - h/2, w, h, color);
}
void Rect(float x, float y, float w, float h,
float u, float v, float uw, float uh, uint32 color);
float u, float v, float uw, float uh, uint32 color);
void V(float x, float y, float z, uint32 color, float u, float v);
void V(float x, float y, uint32 color, float u, float v) {
V(x, y, 0.0f, color, u, v);
}
void Circle(float x, float y, float radius, float thickness, int segments, float startAngle, uint32 color, float u_mul);
void Circle(float x, float y, float radius, float thickness, int segments, float startAngle, uint32 color, float u_mul);
// New drawing APIs
@@ -72,7 +77,7 @@ class DrawBuffer {
void MeasureImage(int atlas_image, float *w, float *h);
void DrawImage(int atlas_image, float x, float y, float scale, Color color = COLOR(0xFFFFFF), int align = ALIGN_TOPLEFT);
void DrawImageStretch(int atlas_image, float x1, float y1, float x2, float y2, Color color = COLOR(0xFFFFFF));
void DrawImageRotated(int atlas_image, float x, float y, float scale, float angle, Color color = COLOR(0xFFFFFF)); // Always centers
void DrawImageRotated(int atlas_image, float x, float y, float scale, float angle, Color color = COLOR(0xFFFFFF)); // Always centers
void DrawTexRect(float x1, float y1, float x2, float y2, float u1, float v1, float u2, float v2, Color color);
// Results in 18 triangles. Kind of expensive for a button.
void DrawImage4Grid(int atlas_image, float x1, float y1, float x2, float y2, Color color = COLOR(0xFFFFFF), float corner_scale = 1.0);
@@ -89,14 +94,21 @@ class DrawBuffer {
fontscaley = ys;
}
// Utility to avoid having to include gl.h just for this in UI code.
void EnableBlend(bool enable);
// Utility to avoid having to include gl.h just for this in UI code.
void EnableBlend(bool enable);
private:
void DoAlign(int align, float *x, float *y, float w, float h);
// Rectangular clipping, implemented using scissoring.
// Must flush before and after.
void SetClipRect(float x1, float y1, float x2, float y2);
void NoClip();
private:
void DoAlign(int flags, float *x, float *y, float *w, float *h);
struct Vertex {
float x, y, z;
uint8 r, g, b, a;
uint32_t rgba;
float u, v;
};
+9 -9
View File
@@ -47,15 +47,15 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil) {
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;
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);
+70 -70
View File
@@ -24,25 +24,25 @@ 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];
GLchar infoLog[MAX_INFO_LOG_SIZE];
GLsizei len;
glGetShaderInfoLog(shader, MAX_INFO_LOG_SIZE, &len, infoLog);
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);
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) {
@@ -50,7 +50,7 @@ GLSLProgram *glsl_create(const char *vshader, const char *fshader) {
program->program_ = 0;
program->vsh_ = 0;
program->fsh_ = 0;
strcpy(program->name, vshader + strlen(vshader) - 15);
strcpy(program->name, vshader + strlen(vshader) - 15);
strcpy(program->vshader_filename, vshader);
strcpy(program->fshader_filename, fshader);
if (glsl_recompile(program)) {
@@ -65,8 +65,8 @@ bool glsl_up_to_date(GLSLProgram *program) {
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;
fs.st_mtime != program->fshader_mtime) {
return false;
} else {
return true;
}
@@ -75,74 +75,74 @@ bool glsl_up_to_date(GLSLProgram *program) {
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);
}
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;
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;
program->fshader_mtime = fs.st_mtime;
else
program->fshader_mtime = 0;
size_t sz;
char *vsh_src = (char *)VFSReadFile(program->vshader_filename, &sz);
char *vsh_src = (char *)VFSReadFile(program->vshader_filename, &sz);
if (!vsh_src) {
ELOG("File missing: %s", vsh_src);
return false;
}
char *fsh_src = (char *)VFSReadFile(program->fshader_filename, &sz);
char *fsh_src = (char *)VFSReadFile(program->fshader_filename, &sz);
if (!fsh_src) {
ELOG("File missing: %s", fsh_src);
delete [] vsh_src;
return false;
}
GLuint vsh = glCreateShader(GL_VERTEX_SHADER);
const GLchar *vsh_str = (const GLchar *)(vsh_src);
if (!CompileShader(vsh_str, vsh, program->vshader_filename)) {
GLuint vsh = glCreateShader(GL_VERTEX_SHADER);
const GLchar *vsh_str = (const GLchar *)(vsh_src);
if (!CompileShader(vsh_str, vsh, program->vshader_filename)) {
return false;
}
delete [] vsh_src;
const GLchar *fsh_str = (const GLchar *)(fsh_src);
GLuint fsh = glCreateShader(GL_FRAGMENT_SHADER);
const GLchar *fsh_str = (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;
delete [] fsh_src;
GLuint prog = glCreateProgram();
glAttachShader(prog, vsh);
glAttachShader(prog, fsh);
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!
}
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!
}
glDeleteShader(vsh);
glDeleteShader(fsh);
return false;
}
return false;
}
// Destroy the old program, if any.
if (program->program_) {
@@ -153,23 +153,23 @@ bool glsl_recompile(GLSLProgram *program) {
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",
//ILOG("Shader compilation success: %s %s",
// program->vshader_filename,
// program->fshader_filename);
return true;
@@ -194,17 +194,17 @@ int glsl_uniform_loc(const GLSLProgram *program, const char *name) {
void glsl_destroy(GLSLProgram *program) {
unregister_gl_resource_holder(program);
glDeleteShader(program->vsh_);
glDeleteShader(program->fsh_);
glDeleteProgram(program->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);
}
+47 -47
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;
}
// Then have generic code here.
// 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.
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);
}
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);
glDisableVertexAttribArray(program->a_normal);
if (vertexFormat & UV0_MASK)
glDisableVertexAttribArray(program->a_texcoord0);
glDisableVertexAttribArray(program->a_texcoord0);
if (vertexFormat & UV1_MASK)
glDisableVertexAttribArray(program->a_texcoord1);
glDisableVertexAttribArray(program->a_texcoord1);
if (vertexFormat & RGBA_MASK)
glDisableVertexAttribArray(program->a_color);
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;
-34
View File
@@ -1,34 +0,0 @@
#ifndef _GFX_SURFACE
#define _GFX_SURFACE
// UNUSED
enum SurfaceFormats {
SURF_ARGB,
SURF_YUV,
};
struct cairo_surface_t;
class Surface {
public:
Surface(int width, int height);
// In case of YUV, U and V channels have half size, rounded UP.
int height() const { return height_; }
int width() const { return width_; }
int pitch() const { return pitch_; }
int half_width() const { return (width_ + 1) >> 1; }
int half_height() const { return (height_ + 1) >> 1; }
cairo_surface_t *CreateCairoSurface();
private:
uint8 *data_;
int width_;
int height_;
int pitch_;
};
#endif
+70 -70
View File
@@ -8,42 +8,42 @@
#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";
@@ -57,13 +57,13 @@ static unsigned int log2i(unsigned int val) {
}
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");
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);
}
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];
@@ -76,14 +76,14 @@ int LoadZIMPtr(uint8_t *zim, int datasize, int *width, int *height, int *flags,
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:
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;
image_data_size[i] = width[i] * height[i] * 2;
break;
case ZIM_ETC1:
{
int data_width = width[i];
@@ -93,47 +93,47 @@ int LoadZIMPtr(uint8_t *zim, int datasize, int *width, int *height, int *flags,
image_data_size[i] = data_width * data_height / 2;
break;
}
default:
ELOG("Invalid ZIM format %i", *flags & ZIM_FORMAT_MASK);
return 0;
}
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);
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);
}
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);
ELOG("Wrong size data in ZIM: %i vs %i", (int)(datasize-16), (int)total_data_size);
}
}
return num_levels;
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;
}
+134 -134
View File
@@ -8,9 +8,9 @@
static const char magic[5] = "ZIMG";
/*int num_levels = 1;
if (flags & ZIM_HAS_MIPS) {
num_levels = log2i(width > height ? width : height);
}*/
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) {
@@ -21,46 +21,46 @@ static unsigned int log2i(unsigned int val) {
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; }
@@ -78,95 +78,95 @@ bool ispowerof2 (int x) {
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);
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; }
}
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);
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;
}
}
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;
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];
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++;
#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);
}
}
}
break;
default:
ELOG("Unhandled ZIM format %i", flags & ZIM_FORMAT_MASK);
*data = 0;
*data_size = 0;
return;
}
}
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;
}
}
// Deletes the old buffer.
@@ -199,28 +199,28 @@ uint8_t *DownsampleBy2(const uint8_t *image, int width, int height, int pitch) {
}
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;
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");
}
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);
@@ -243,5 +243,5 @@ void SaveZIM(const char *filename, int width, int height, int pitch, int flags,
}
}
delete [] image_data;
fclose(f);
fclose(f);
}
+35 -35
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,43 +26,43 @@ struct Finger {
static Finger fingers[MAX_FINGERS];
void update(const InputState &state) {
// Mouse / 1-finger-touch control.
if (state.mouse_down[0]) {
fingers[0].down = true;
fingers[0].downX = state.mouse_x[0];
fingers[0].downY = state.mouse_y[0];
} else {
fingers[0].down = false;
}
// Mouse / 1-finger-touch control.
if (state.mouse_down[0]) {
fingers[0].down = true;
fingers[0].downX = state.mouse_x[0];
fingers[0].downY = state.mouse_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;
if (!fingers[i].down) {
return false;
}
*xdelta = fingers[i].downX;
*ydelta = fingers[i].downY;
}
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;
*xdelta = fingers[i].X - fingers[i].downX;
*ydelta = fingers[i].Y - fingers[i].downY;
}
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;
*xdelta = fingers[i].X - fingers[i].lastX;
*ydelta = fingers[i].Y - fingers[i].lastY;
}
}
+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);
};
+14 -14
View File
@@ -21,22 +21,22 @@ 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(mouse_down, 0, sizeof(mouse_down));
memset(mouse_last, 0, sizeof(mouse_last));
}
// 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(mouse_down, 0, sizeof(mouse_down));
memset(mouse_last, 0, sizeof(mouse_last));
}
// Gamepad style input
int pad_buttons; // bitfield
@@ -51,7 +51,7 @@ struct InputState {
float pad_rtrigger;
// Mouse/touch style input
// There are up to 8 mice / fingers.
// There are up to 8 mice / fingers.
volatile bool mouse_valid;
int mouse_x[MAX_POINTERS];
+8 -8
View File
@@ -103,13 +103,13 @@ 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;
case ARRAY:
str_ << "\n" << indent() << "]";
break;
case DICT:
str_ << "\n" << indent() << "}";
break;
}
if (stack_.size() > 0)
stack_.back().first = false;
if (stack_.size() > 0)
stack_.back().first = false;
}
+4 -4
View File
@@ -17,14 +17,14 @@
#include "base/basictypes.h"
class JsonWriter {
public:
public:
JsonWriter();
~JsonWriter();
void begin();
void end();
void pushDict(const char *name);
void pushArray(const char *name);
void pop();
void pop();
void writeBool(bool value);
void writeBool(const char *name, bool value);
void writeInt(int value);
@@ -38,7 +38,7 @@ class JsonWriter {
return str_.str();
}
private:
private:
const char *indent(int n) const;
const char *comma() const;
const char *arrayComma() const;
@@ -56,5 +56,5 @@ class JsonWriter {
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];
}
}
+181 -181
View File
@@ -14,189 +14,189 @@
// 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.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.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.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.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;
}
Matrix4x4 Matrix4x4::simpleInverse() const {
Matrix4x4 out;
out.xx = xx;
out.xy = yx;
out.xz = zx;
out.yx = xy;
out.yy = yy;
out.yz = zy;
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.xw = 0.0f;
out.yw = 0.0f;
out.zw = 0.0f;
out.ww = 1.0f;
Matrix4x4 out;
out.xx = xx;
out.xy = yx;
out.xz = zx;
return out;
out.yx = xy;
out.yy = yy;
out.yz = zy;
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.xw = 0.0f;
out.yw = 0.0f;
out.zw = 0.0f;
out.ww = 1.0f;
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));
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.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;
return temp;
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.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.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;
}
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) {
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;
wx = -vFrom * vRight;
wy = -vFrom * vUp;
wz = -vFrom * vView;
ww = 1.0f;
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;
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();
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;
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;
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;
wx = -pos * vRight;
wy = -pos * vUp;
wz = -pos * vView;
ww = 1.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;
}
//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();
empty();
float xFac = tanf(fov_horiz * 3.14f/360);
float yFac = xFac * aspect;
@@ -208,17 +208,17 @@ void Matrix4x4::setProjection(float near, float far, float fov_horiz, float aspe
}
void Matrix4x4::setProjectionD3D(float near_plane, float far_plane, float fov_horiz, float aspect) {
empty();
float Q, f;
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;
empty();
float Q, f;
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;
}
void Matrix4x4::setOrtho(float left, float right, float bottom, float top, float near, float far) {
@@ -233,43 +233,43 @@ void Matrix4x4::setOrtho(float left, float right, float bottom, float top, float
// 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;
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;
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);
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';
}
+106 -106
View File
@@ -6,17 +6,17 @@
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;
public:
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;
}
@@ -31,110 +31,110 @@ class Matrix4x4 {
}
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 &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;
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 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);
}
Matrix4x4 inverse() const;
Matrix4x4 simpleInverse() const;
Matrix4x4 transpose() const;
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 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 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 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;
}
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);
static Matrix4x4 fromPRS(const Vec3 &position, const Quaternion &normal, const Vec3 &scale);
};
#endif // _MATH_LIN_MATRIX4X4_H
+95 -95
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;
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.zx = xz + wy;
temp.zy = yz - wx;
temp.zz = ww - xx - yy + zz;
*out = temp;
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.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;
*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);
// 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;
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;
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 ((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
);
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
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;
}
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;
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);
float x,y,z,w;
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() { }
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;
}
};
#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);
}
+102 -102
View File
@@ -18,112 +18,112 @@ 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;
Vec3() { }
explicit Vec3(float f) {x=y=z=f;}
float 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() { }
explicit Vec3(float f) {x=y=z=f;}
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(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);
}
};
inline Vec3 operator * (const float f, const Vec3 &v) {return v * f;}
@@ -144,8 +144,8 @@ inline float sqr(const Vec3 &v) {
class AABBox {
public:
Vec3 min;
Vec3 max;
Vec3 min;
Vec3 max;
};
#endif // _MATH_LIN_VEC3
-19
View File
@@ -1,19 +0,0 @@
#include "math/math_util.h"
#include <math.h>
#include <stdlib.h>
/*
static unsigned int randSeed = 22222; // Change this for different random sequences.
void SetSeed(unsigned int seed) {
randSeed = seed * 382792592;
}
unsigned int GenerateRandomNumber() {
randSeed = (randSeed * 196314165) + 907633515;
randSeed ^= _rotl(randSeed, 13);
return randSeed;
}*/
#include <math.h>
+53
View File
@@ -0,0 +1,53 @@
#include "math/math_util.h"
#include <math.h>
#include <stdlib.h>
/*
static unsigned int randSeed = 22222; // Change this for different random sequences.
void SetSeed(unsigned int seed) {
randSeed = seed * 382792592;
}
unsigned int GenerateRandomNumber() {
randSeed = (randSeed * 196314165) + 907633515;
randSeed ^= _rotl(randSeed, 13);
return randSeed;
}*/
#include <math.h>
#ifdef ANDROID
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);
}
void DisableFZ( )
{
__asm__ volatile(
"fmrx r0, fpscr\n"
"bic r0, $(1 << 24)\n"
"fmxr fpscr, r0" : : : "r0");
}
#else
void EnableFZ()
{
}
void DisableFZ()
{
}
#endif
+25 -37
View File
@@ -8,16 +8,17 @@ typedef unsigned short float16;
// This ain't a 1.5.10 float16, it's a stupid hack format where we chop 16 bits off a float.
// 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;
}
@@ -26,62 +27,49 @@ inline float Float16ToFloat(float16 ix) {
// The stuff in this file is from all over the web, esp. dspmusic.org. I think it's all public domain.
// In any case, very little of it is used anywhere at the moment.
// PM modulated sine
inline float sine(float t,float f,float ph,float fm) {
return sinf((t*f+ph)*2*PI + 0.5f*PI*fm*(1 - sqrt(f*2)));
}
//fb := feedback (0 to 1) (1 max saw)
inline float saw(float t,float f,float ph, float fm, float fb = 1.0f)
{
return sine(t,f,ph,fb*sine(t-1.0f,f,ph,fm));
}
// pm := pulse mod (0 to 1) (1 max pulse)
// pw := pulse width (0 to 1) (1 square)
inline float pulse(float t,float f,float ph,float fm,float fb,float pm,float pw) {
return saw(t,f,ph,fm,fb) - saw(t,f,ph+0.5f*pw,fm,fb) * pm;
}
// Calculate pseudo-random 32 bit number based on linear congruential method.
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 log(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 exp(dB * DB_2_LOG);
const float DB_2_LOG = 0.11512925464970228420089957273422f; // ln( 10 ) / 20
return expf(dB * DB_2_LOG);
}
// FPU control.
void EnableFZ();
void DisableFZ();
#endif
+40 -41
View File
@@ -13,53 +13,52 @@
#include "midi/midi_input.h"
std::vector<std::string> MidiInGetDevices() {
int numDevs = midiInGetNumDevs();
std::vector<std::string> devices;
for (int i = 0; i < numDevs; i++) {
MIDIINCAPS caps;
midiInGetDevCaps(i, &caps, sizeof(caps));
devices.push_back(caps.szPname);
}
return devices;
int numDevs = midiInGetNumDevs();
std::vector<std::string> devices;
for (int i = 0; i < numDevs; i++) {
MIDIINCAPS caps;
midiInGetDevCaps(i, &caps, sizeof(caps));
devices.push_back(caps.szPname);
}
return devices;
}
static void CALLBACK MidiCallback(HMIDIIN hMidiIn, UINT wMsg, DWORD_PTR dwInstance,
DWORD_PTR dwParam1, DWORD_PTR dwParam2) {
MidiListener *listener = (MidiListener*)dwInstance;
uint8_t cmd[3] = {0};
static void CALLBACK MidiCallback(HMIDIIN hMidiIn, UINT wMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) {
MidiListener *listener = (MidiListener*)dwInstance;
uint8_t cmd[3] = {0};
switch (wMsg) {
case MM_MIM_OPEN:
ILOG("Got MIDI Open message");
break;
case MM_MIM_CLOSE:
ILOG("Got MIDI Close message");
break;
case MM_MIM_DATA:
cmd[0] = dwParam1 & 0xFF;
cmd[1] = (dwParam1 >> 8) & 0xFF;
cmd[2] = (dwParam1 >> 16) & 0xFF;
// time = dwParam2 & 0xFFFF;
ILOG("Got MIDI Data: %02x %02x %02x", cmd[0], cmd[1], cmd[2]);
listener->midiEvent(cmd);
break;
default:
WLOG("Got unexpected MIDI message: %08x", (uint32_t)wMsg);
break;
}
switch (wMsg) {
case MM_MIM_OPEN:
ILOG("Got MIDI Open message");
break;
case MM_MIM_CLOSE:
ILOG("Got MIDI Close message");
break;
case MM_MIM_DATA:
cmd[0] = dwParam1 & 0xFF;
cmd[1] = (dwParam1 >> 8) & 0xFF;
cmd[2] = (dwParam1 >> 16) & 0xFF;
// time = dwParam2 & 0xFFFF;
ILOG("Got MIDI Data: %02x %02x %02x", cmd[0], cmd[1], cmd[2]);
listener->midiEvent(cmd);
break;
default:
WLOG("Got unexpected MIDI message: %08x", (uint32_t)wMsg);
break;
}
}
MidiDevice MidiInStart(int deviceID, MidiListener *listener) {
HMIDIIN hMidiIn;
MMRESULT result = midiInOpen(&hMidiIn, deviceID, (DWORD_PTR)(&MidiCallback), (DWORD_PTR)listener, CALLBACK_FUNCTION);
midiInStart(hMidiIn);
return (MidiDevice)hMidiIn;
HMIDIIN hMidiIn;
MMRESULT result = midiInOpen(&hMidiIn, deviceID, (DWORD_PTR)(&MidiCallback), (DWORD_PTR)listener, CALLBACK_FUNCTION);
midiInStart(hMidiIn);
return (MidiDevice)hMidiIn;
}
void MidiInStop(MidiDevice device) {
HMIDIIN hMidiIn = (HMIDIIN)device;
midiInStop(hMidiIn);
midiInClose(hMidiIn);
HMIDIIN hMidiIn = (HMIDIIN)device;
midiInStop(hMidiIn);
midiInClose(hMidiIn);
}
#else
@@ -74,15 +73,15 @@ void MidiInStop(MidiDevice device) {
// Stubs for other platforms.
std::vector<std::string> MidiInGetDevices() {
return std::vector<std::string>();
return std::vector<std::string>();
}
MidiDevice MidiInStart(int deviceID, MidiListener *listener) {
FLOG("Invalid MIDI device");
FLOG("Invalid MIDI device");
}
void MidiInStop(MidiDevice device) {
FLOG("Invalid MIDI device");
FLOG("Invalid MIDI device");
}
#endif
+2 -1
View File
@@ -16,7 +16,8 @@ typedef void *MidiDevice;
class MidiListener
{
public:
virtual void midiEvent(const uint8_t *cmd) = 0;
virtual ~MidiListener() {}
virtual void midiEvent(const uint8_t *cmd) = 0;
};
// Gets the names of the devices in a vector. The device identifier is the index in the vector.
+19 -2
View File
@@ -62,6 +62,9 @@
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
<Lib>
<AdditionalDependencies>Ws2_32.lib</AdditionalDependencies>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
@@ -80,6 +83,9 @@
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
<Lib>
<AdditionalDependencies>Ws2_32.lib</AdditionalDependencies>
</Lib>
</ItemDefinitionGroup>
<ItemGroup>
<None Include="file\CMakeLists.txt" />
@@ -89,6 +95,7 @@
<ClInclude Include="audio\mixer.h" />
<ClInclude Include="audio\wav_read.h" />
<ClInclude Include="base\basictypes.h" />
<ClInclude Include="base\buffer.h" />
<ClInclude Include="base\color.h" />
<ClInclude Include="base\colorutil.h" />
<ClInclude Include="base\display.h" />
@@ -101,6 +108,7 @@
<ClInclude Include="base\stats.h" />
<ClInclude Include="base\stringutil.h" />
<ClInclude Include="base\timeutil.h" />
<ClInclude Include="data\listable.h" />
<ClInclude Include="ext\etcpack\etcdec.h" />
<ClInclude Include="ext\etcpack\etcpack.h" />
<ClInclude Include="ext\sha1\sha1.h" />
@@ -110,6 +118,7 @@
<ClInclude Include="file\chunk_file.h" />
<ClInclude Include="file\dialog.h" />
<ClInclude Include="file\easy_file.h" />
<ClInclude Include="file\fd_util.h" />
<ClInclude Include="file\file_util.h" />
<ClInclude Include="file\vfs.h" />
<ClInclude Include="file\zip_read.h" />
@@ -123,7 +132,6 @@
<ClInclude Include="gfx_es2\glsl_program.h" />
<ClInclude Include="gfx_es2\vertex_format.h" />
<ClInclude Include="image\png_load.h" />
<ClInclude Include="image\surface.h" />
<ClInclude Include="image\zim_load.h" />
<ClInclude Include="image\zim_save.h" />
<ClInclude Include="input\gesture_detector.h" />
@@ -135,8 +143,11 @@
<ClInclude Include="math\lin\vec3.h" />
<ClInclude Include="math\math_util.h" />
<ClInclude Include="midi\midi_input.h" />
<ClInclude Include="net\http_client.h" />
<ClInclude Include="net\resolve.h" />
<ClInclude Include="profiler\profiler.h" />
<ClInclude Include="ui\ui.h" />
<ClInclude Include="util\bits\bits.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="android\app-android.cpp">
@@ -145,10 +156,12 @@
</ClCompile>
<ClCompile Include="audio\mixer.cpp" />
<ClCompile Include="audio\wav_read.cpp" />
<ClCompile Include="base\buffer.cpp" />
<ClCompile Include="base\colorutil.cpp" />
<ClCompile Include="base\display.cpp" />
<ClCompile Include="base\error_context.cpp" />
<ClCompile Include="base\LAMEString.cpp" />
<ClCompile Include="base\stringutil.cpp" />
<ClCompile Include="base\timeutil.cpp" />
<ClCompile Include="ext\etcpack\etcdec.cpp" />
<ClCompile Include="ext\etcpack\etcpack.cpp" />
@@ -163,6 +176,7 @@
<ClCompile Include="file\chunk_file.cpp" />
<ClCompile Include="file\dialog.cpp" />
<ClCompile Include="file\easy_file.cpp" />
<ClCompile Include="file\fd_util.cpp" />
<ClCompile Include="file\file_util.cpp" />
<ClCompile Include="file\zip_read.cpp" />
<ClCompile Include="gfx\gl_debug_log.cpp" />
@@ -182,10 +196,13 @@
<ClCompile Include="math\lin\matrix4x4.cpp" />
<ClCompile Include="math\lin\quat.cpp" />
<ClCompile Include="math\lin\vec3.cpp" />
<ClCompile Include="math\math_util.cc" />
<ClCompile Include="math\math_util.cpp" />
<ClCompile Include="midi\midi_input.cpp" />
<ClCompile Include="net\http_client.cpp" />
<ClCompile Include="net\resolve.cpp" />
<ClCompile Include="profiler\profiler.cpp" />
<ClCompile Include="ui\ui.cpp" />
<ClCompile Include="util\bits\bits.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
+54 -5
View File
@@ -7,8 +7,6 @@
<None Include="README.md" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="base\logging.h" />
<ClInclude Include="image\surface.h" />
<ClInclude Include="gfx\gl_debug_log.h">
<Filter>gfx</Filter>
</ClInclude>
@@ -156,6 +154,27 @@
<ClInclude Include="base\mutex.h">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="util\bits\bits.h">
<Filter>util</Filter>
</ClInclude>
<ClInclude Include="data\listable.h">
<Filter>data</Filter>
</ClInclude>
<ClInclude Include="base\logging.h">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="net\http_client.h">
<Filter>net</Filter>
</ClInclude>
<ClInclude Include="base\buffer.h">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="file\fd_util.h">
<Filter>file</Filter>
</ClInclude>
<ClInclude Include="net\resolve.h">
<Filter>net</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="gfx\gl_debug_log.cpp">
@@ -218,9 +237,6 @@
<ClCompile Include="gfx\texture_atlas.cpp">
<Filter>gfx</Filter>
</ClCompile>
<ClCompile Include="math\math_util.cc">
<Filter>math</Filter>
</ClCompile>
<ClCompile Include="ext\etcpack\etcpack.cpp">
<Filter>ext</Filter>
</ClCompile>
@@ -281,6 +297,27 @@
<ClCompile Include="android\app-android.cpp">
<Filter>base</Filter>
</ClCompile>
<ClCompile Include="util\bits\bits.cpp">
<Filter>util</Filter>
</ClCompile>
<ClCompile Include="math\math_util.cpp">
<Filter>math</Filter>
</ClCompile>
<ClCompile Include="net\http_client.cpp">
<Filter>net</Filter>
</ClCompile>
<ClCompile Include="base\buffer.cpp">
<Filter>base</Filter>
</ClCompile>
<ClCompile Include="file\fd_util.cpp">
<Filter>file</Filter>
</ClCompile>
<ClCompile Include="base\stringutil.cpp">
<Filter>base</Filter>
</ClCompile>
<ClCompile Include="net\resolve.cpp">
<Filter>net</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Filter Include="gfx">
@@ -322,5 +359,17 @@
<Filter Include="midi">
<UniqueIdentifier>{4710a9a2-d1fa-4920-ba1b-a7527902be53}</UniqueIdentifier>
</Filter>
<Filter Include="util">
<UniqueIdentifier>{e36ca540-863c-496b-b0f4-b1ece3e72feb}</UniqueIdentifier>
</Filter>
<Filter Include="data">
<UniqueIdentifier>{d5fa3d62-88bf-4dc4-9814-28f3c0444e62}</UniqueIdentifier>
</Filter>
<Filter Include="io">
<UniqueIdentifier>{1e85f968-7106-483c-ae7d-77d0ef58d787}</UniqueIdentifier>
</Filter>
<Filter Include="net">
<UniqueIdentifier>{6a548b3d-3a4c-4114-aa2f-0b42bf7bf2ce}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>
+11
View File
@@ -0,0 +1,11 @@
set(SRCS
http_client.cpp
resolve.cpp)
set(SRCS ${SRCS})
add_library(net STATIC ${SRCS})
if(UNIX)
add_definitions(-fPIC)
endif(UNIX)
+147
View File
@@ -0,0 +1,147 @@
#include "net/http_client.h"
// for inet_pton
#define _WIN32_WINNT 0x600
#ifndef _WIN32
#include <arpa/inet.h>
#include <sys/socket.h>
#include <unistd.h>
#define closesocket close
#else
#include <winsock2.h>
#include <ws2tcpip.h>
#include <io.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include "base/logging.h"
#include "base/buffer.h"
#include "base/stringutil.h"
#include "net/resolve.h"
// #include "strings/strutil.h"
namespace net {
Connection::Connection()
: port_(-1), sock_(-1) {
}
Connection::~Connection() {
Disconnect();
}
bool Connection::Resolve(const char *host, int port) {
CHECK_EQ(-1, 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);
return true;
}
void Connection::Connect() {
CHECK_GE(port_, 0);
sock_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
CHECK_GE(sock_, 0);
//VLOG(1) << "Connecting to " << host_ << ":" << port_;
// 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);
#else
sleep(1);
#endif
}
}
void Connection::Disconnect() {
if (sock_ != -1) {
closesocket(sock_);
sock_ = -1;
} else {
WLOG("Socket was already disconnected.");
}
}
void Connection::Reconnect() {
Disconnect();
Connect();
}
} // net
namespace http {
Client::Client() {
}
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()));
// Snarf all the data we can.
output->ReadAll(sock());
// Skip the header.
while (output->SkipLineCRLF() > 0)
;
// 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()));
// I guess we could add a deadline here.
output->ReadAll(sock());
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;
}
} // http
+66
View File
@@ -0,0 +1,66 @@
#ifndef _NET_HTTP_HTTP_CLIENT
#define _NET_HTTP_HTTP_CLIENT
#include "base/basictypes.h"
#include "base/buffer.h"
#ifndef _WIN32
#include <arpa/inet.h>
#include <sys/socket.h>
#else
#include <winsock2.h>
#endif
namespace net {
class Connection {
public:
Connection();
virtual ~Connection();
// Inits the sockaddr_in.
bool Resolve(const char *host, int port);
void Connect();
void Disconnect();
// Disconnects, and connects. Doesn't re-resolve.
void Reconnect();
// 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_;
private:
uintptr_t sock_;
};
} // namespace net
namespace http {
class Client : public net::Connection {
public:
Client();
~Client();
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);
// HEAD, PUT, DELETE aren't implemented yet.
};
} // http
#endif // _NET_HTTP_HTTP_CLIENT
+48
View File
@@ -0,0 +1,48 @@
#include "net/resolve.h"
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#ifndef _WIN32
#include <arpa/inet.h>
#include <netdb.h> // gethostbyname
#else
#include <WinSock2.h>
#include <Ws2tcpip.h>
#endif
namespace net {
void Init()
{
#ifdef _WIN32
WSADATA wsaData = {0};
WSAStartup(MAKEWORD(2, 2), &wsaData);
#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;
}
}
+12
View File
@@ -0,0 +1,12 @@
#ifndef _NET_RESOLVE_H
#define _NET_RESOLVE_H
namespace net {
// Required on Win32
void Init();
// use free() to free the returned string.
char *DNSResolve(const char *host);
} // namespace net
#endif
+1 -1
View File
@@ -42,7 +42,7 @@ void _profiler_leave(const char *section_name) {
cur_section[level].end = real_time_now();
if (strcmp(section_name, cur_section[level].name)) {
FLOG("Can't enter %s when %s is active, only one at a time!",
section_name, cur_section[level].name);
section_name, cur_section[level].name);
}
cur_section[level].level = level;
current_frame.push_back(cur_section[level]);
+217 -208
View File
@@ -7,6 +7,7 @@
#include "gfx/texture_atlas.h"
#include "gfx_es2/draw_buffer.h"
// TODO: UI should probably not own these.
DrawBuffer ui_draw2d;
DrawBuffer ui_draw2d_front;
UIState uistate;
@@ -19,31 +20,36 @@ static int themeCheckOnImage;
static int themeCheckOffImage;
void UIInit(const Atlas *atlas, int uiFont, int buttonImage, int checkOn, int checkOff) {
ui_draw2d.SetAtlas(atlas);
ui_draw2d.SetAtlas(atlas);
ui_draw2d_front.SetAtlas(atlas);
themeAtlas = atlas;
themeUIFont = uiFont;
themeButtonImage = buttonImage;
themeCheckOnImage = checkOn;
themeCheckOffImage = checkOff;
themeAtlas = atlas;
themeUIFont = uiFont;
themeButtonImage = buttonImage;
themeCheckOnImage = checkOn;
themeCheckOffImage = checkOff;
memset(&uistate, 0, sizeof(uistate));
}
void UIUpdateMouse(int i, float x, float y, bool down) {
if (down && !uistate.mousedown[i]) {
uistate.mousepressed[i] = 1;
uistate.mouseStartX[i] = x;
uistate.mouseStartY[i] = y;
} else {
uistate.mousepressed[i] = 0;
}
if (down && !uistate.mousedown[i]) {
uistate.mousepressed[i] = 1;
uistate.mouseStartX[i] = x;
uistate.mouseStartY[i] = y;
} else {
uistate.mousepressed[i] = 0;
}
if (uistate.mousedown[i])
uistate.mouseframesdown[i]++;
else
uistate.mouseframesdown[i] = 0;
uistate.mousex[i] = x;
uistate.mousey[i] = y;
uistate.mousedown[i] = down;
uistate.mousex[i] = x;
uistate.mousey[i] = y;
uistate.mousedown[i] = down;
}
bool UIRegionHit(int i, int x, int y, int w, int h, int margin) {
// Input handling
// Input handling
if (uistate.mousex[i] < x - margin ||
uistate.mousey[i] < y - margin ||
uistate.mousex[i] >= x + w + margin ||
@@ -55,245 +61,248 @@ bool UIRegionHit(int i, int x, int y, int w, int h, int margin) {
}
void UIBegin() {
for (int i = 0; i < MAX_POINTERS; i++)
uistate.hotitem[i] = 0;
for (int i = 0; i < MAX_POINTERS; i++)
uistate.hotitem[i] = 0;
ui_draw2d.Begin();
ui_draw2d_front.Begin();
ui_draw2d_front.Begin();
}
void UIEnd() {
for (int i = 0; i < MAX_POINTERS; i++) {
if (uistate.mousedown[i] == 0) {
uistate.activeitem[i] = 0;
} else {
if (uistate.activeitem[i] == 0) {
uistate.activeitem[i] = -1;
}
}
}
ui_draw2d.End();
for (int i = 0; i < MAX_POINTERS; i++) {
if (uistate.mousedown[i] == 0) {
uistate.activeitem[i] = 0;
} else {
if (uistate.activeitem[i] == 0) {
uistate.activeitem[i] = -1;
}
}
}
ui_draw2d.End();
ui_draw2d_front.End();
if (uistate.ui_tick > 0)
uistate.ui_tick--;
}
void UIText(int x, int y, const char *text, uint32_t color, float scale, int align) {
UIText(themeUIFont, x, y, text, color, scale, align);
UIText(themeUIFont, x, y, text, color, scale, align);
}
void UIText(int font, int x, int y, const char *text, uint32_t color, float scale, int align) {
ui_draw2d.SetFontScale(scale, scale);
ui_draw2d.DrawTextShadow(font, text, x, y, color, align);
ui_draw2d.SetFontScale(1.0f, 1.0f);
ui_draw2d.SetFontScale(scale, scale);
ui_draw2d.DrawTextShadow(font, text, x, y, color, align);
ui_draw2d.SetFontScale(1.0f, 1.0f);
}
int UIButton(int id, const LayoutManager &layout, float w, const char *text, int button_align) {
float h = themeAtlas->images[themeButtonImage].h;
float x, y;
layout.GetPos(&w, &h, &x, &y);
if (button_align & ALIGN_HCENTER) x -= w / 2;
if (button_align & ALIGN_VCENTER) y -= h / 2;
if (button_align & ALIGN_RIGHT) x -= w;
if (button_align & ALIGN_BOTTOMRIGHT) y -= h;
float x, y;
layout.GetPos(&w, &h, &x, &y);
int txOffset = 0;
if (button_align & ALIGN_HCENTER) x -= w / 2;
if (button_align & ALIGN_VCENTER) y -= h / 2;
if (button_align & ALIGN_RIGHT) x -= w;
if (button_align & ALIGN_BOTTOMRIGHT) y -= h;
int clicked = 0;
for (int i = 0; i < MAX_POINTERS; i++) {
// Check whether the button should be hot, use a generous margin for touch ease
if (UIRegionHit(i, x, y, w, h, 8)) {
uistate.hotitem[i] = id;
if (uistate.activeitem[i] == 0 && uistate.mousedown[i])
uistate.activeitem[i] = id;
}
int txOffset = 0;
if (uistate.hotitem[i] == id) {
if (uistate.activeitem[i] == id) {
// Button is both 'hot' and 'active'
txOffset = 2;
} else {
// Button is merely 'hot'
}
} else {
// button is not hot, but it may be active
}
int clicked = 0;
for (int i = 0; i < MAX_POINTERS; i++) {
// Check whether the button should be hot, use a generous margin for touch ease
if (UIRegionHit(i, x, y, w, h, 8)) {
uistate.hotitem[i] = id;
if (uistate.activeitem[i] == 0 && uistate.mousedown[i])
uistate.activeitem[i] = id;
}
if (uistate.hotitem[i] == id) {
if (uistate.activeitem[i] == id) {
// Button is both 'hot' and 'active'
txOffset = 2;
} else {
// Button is merely 'hot'
}
} else {
// button is not hot, but it may be active
}
// If button is hot and active, but mouse button is not
// down, the user must have clicked the button.
if (uistate.mousedown[i] == 0 &&
uistate.hotitem[i] == id &&
uistate.activeitem[i] == id) {
clicked = 1;
}
}
// If button is hot and active, but mouse button is not
// down, the user must have clicked the button.
if (uistate.mousedown[i] == 0 &&
uistate.hotitem[i] == id &&
uistate.activeitem[i] == id) {
clicked = 1;
}
}
// Render button
ui_draw2d.DrawImage2GridH(themeButtonImage, x, y, x + w);
ui_draw2d.DrawTextShadow(themeUIFont, text, x + w/2, y + h/2 + txOffset, 0xFFFFFFFF, ALIGN_HCENTER | ALIGN_VCENTER);
uistate.lastwidget = id;
return clicked;
uistate.lastwidget = id;
return clicked;
}
int UIImageButton(int id, const LayoutManager &layout, float w, int image, int button_align) {
float h = 64;
float x, y;
layout.GetPos(&w, &h, &x, &y);
float h = 64;
float x, y;
layout.GetPos(&w, &h, &x, &y);
if (button_align & ALIGN_HCENTER) x -= w / 2;
if (button_align & ALIGN_VCENTER) y -= h / 2;
if (button_align & ALIGN_RIGHT) x -= w;
if (button_align & ALIGN_BOTTOMRIGHT) y -= h;
if (button_align & ALIGN_HCENTER) x -= w / 2;
if (button_align & ALIGN_VCENTER) y -= h / 2;
if (button_align & ALIGN_RIGHT) x -= w;
if (button_align & ALIGN_BOTTOMRIGHT) y -= h;
int txOffset = 0;
int clicked = 0;
for (int i = 0; i < MAX_POINTERS; i++) {
// Check whether the button should be hot, use a generous margin for touch ease
if (UIRegionHit(i, x, y, w, h, 8)) {
uistate.hotitem[i] = id;
if (uistate.activeitem[i] == 0 && uistate.mousedown[i])
uistate.activeitem[i] = id;
}
int txOffset = 0;
int clicked = 0;
for (int i = 0; i < MAX_POINTERS; i++) {
// Check whether the button should be hot, use a generous margin for touch ease
if (UIRegionHit(i, x, y, w, h, 8)) {
uistate.hotitem[i] = id;
if (uistate.activeitem[i] == 0 && uistate.mousedown[i])
uistate.activeitem[i] = id;
}
if (uistate.hotitem[i] == id) {
if (uistate.activeitem[i] == id) {
// Button is both 'hot' and 'active'
txOffset = 2;
} else {
// Button is merely 'hot'
}
} else {
// button is not hot, but it may be active
}
if (uistate.hotitem[i] == id) {
if (uistate.activeitem[i] == id) {
// Button is both 'hot' and 'active'
txOffset = 2;
} else {
// Button is merely 'hot'
}
} else {
// button is not hot, but it may be active
}
// If button is hot and active, but mouse button is not
// down, the user must have clicked the button.
if (uistate.mousedown[i] == 0 &&
uistate.hotitem[i] == id &&
uistate.activeitem[i] == id) {
clicked = 1;
}
}
// If button is hot and active, but mouse button is not
// down, the user must have clicked the button.
if (uistate.mousedown[i] == 0 &&
uistate.hotitem[i] == id &&
uistate.activeitem[i] == id) {
clicked = 1;
}
}
// Render button
// Render button
ui_draw2d.DrawImage2GridH(themeButtonImage, x, y, x + w);
ui_draw2d.DrawImage(image, x + w/2, y + h/2 + txOffset, 1.0f, 0xFFFFFFFF, ALIGN_HCENTER | ALIGN_VCENTER);
ui_draw2d.DrawImage2GridH(themeButtonImage, x, y, x + w);
ui_draw2d.DrawImage(image, x + w/2, y + h/2 + txOffset, 1.0f, 0xFFFFFFFF, ALIGN_HCENTER | ALIGN_VCENTER);
uistate.lastwidget = id;
return clicked;
uistate.lastwidget = id;
return clicked;
}
int UICheckBox(int id, int x, int y, const char *text, int align, bool *value) {
const int h = 64;
float tw, th;
ui_draw2d.MeasureText(themeUIFont, text, &tw, &th);
int w = themeAtlas->images[themeCheckOnImage].w + UI_SPACE + tw;
if (align & ALIGN_HCENTER) x -= w / 2;
if (align & ALIGN_VCENTER) y -= h / 2;
if (align & ALIGN_RIGHT) x -= w;
if (align & ALIGN_BOTTOMRIGHT) y -= h;
float tw, th;
ui_draw2d.MeasureText(themeUIFont, text, &tw, &th);
int w = themeAtlas->images[themeCheckOnImage].w + UI_SPACE + tw;
if (align & ALIGN_HCENTER) x -= w / 2;
if (align & ALIGN_VCENTER) y -= h / 2;
if (align & ALIGN_RIGHT) x -= w;
if (align & ALIGN_BOTTOMRIGHT) y -= h;
int txOffset = 0;
int clicked = 0;
for (int i = 0; i < MAX_POINTERS; i++) {
int txOffset = 0;
int clicked = 0;
for (int i = 0; i < MAX_POINTERS; i++) {
// Check whether the button should be hot
if (UIRegionHit(i, x, y, w, h, 8)) {
uistate.hotitem[i] = id;
if (uistate.activeitem[i] == 0 && uistate.mousedown[i])
uistate.activeitem[i] = id;
}
// Render button
// Check whether the button should be hot
if (UIRegionHit(i, x, y, w, h, 8)) {
uistate.hotitem[i] = id;
if (uistate.activeitem[i] == 0 && uistate.mousedown[i])
uistate.activeitem[i] = id;
}
if (uistate.hotitem[i] == id) {
if (uistate.activeitem[i] == id) {
// Button is both 'hot' and 'active'
txOffset = 2;
} else {
// Button is merely 'hot'
}
} else {
// button is not hot, but it may be active
}
// If button is hot and active, but mouse button is not
// down, the user must have clicked the button.
if (uistate.mousedown[i] == 0 &&
uistate.hotitem[i] == id &&
uistate.activeitem[i] == id) {
*value = !(*value);
clicked = 1;
}
}
// Render button
ui_draw2d.DrawImage((*value) ? themeCheckOnImage : themeCheckOffImage, x, y+h/2, 1.0f, 0xFFFFFFFF, ALIGN_LEFT | ALIGN_VCENTER);
if (uistate.hotitem[i] == id) {
if (uistate.activeitem[i] == id) {
// Button is both 'hot' and 'active'
txOffset = 2;
} else {
// Button is merely 'hot'
}
} else {
// button is not hot, but it may be active
}
// If button is hot and active, but mouse button is not
// down, the user must have clicked the button.
if (uistate.mousedown[i] == 0 &&
uistate.hotitem[i] == id &&
uistate.activeitem[i] == id) {
*value = !(*value);
clicked = 1;
}
}
ui_draw2d.DrawImage((*value) ? themeCheckOnImage : themeCheckOffImage, x, y+h/2, 1.0f, 0xFFFFFFFF, ALIGN_LEFT | ALIGN_VCENTER);
ui_draw2d.DrawTextShadow(themeUIFont, text, x + themeAtlas->images[themeCheckOnImage].w + UI_SPACE, y + txOffset + h/2, 0xFFFFFFFF, ALIGN_LEFT | ALIGN_VCENTER);
uistate.lastwidget = id;
return clicked;
uistate.lastwidget = id;
return clicked;
}
void StringVectorListAdapter::drawItem(int item, int x, int y, int w, int h, bool selected) const
{
ui_draw2d.DrawImage2GridH(themeButtonImage, x, y, x + w);
ui_draw2d.DrawTextShadow(themeUIFont, (*items_)[item].c_str(), x + UI_SPACE , y, 0xFFFFFFFF, ALIGN_LEFT | ALIGN_VCENTER);
ui_draw2d.DrawImage2GridH(themeButtonImage, x, y, x + w);
ui_draw2d.DrawTextShadow(themeUIFont, (*items_)[item].c_str(), x + UI_SPACE , y, 0xFFFFFFFF, ALIGN_LEFT | ALIGN_VCENTER);
}
int UIList(int id, int x, int y, int w, int h, UIListAdapter *adapter, UIListState *state) {
const int item_h = 64;
int clicked = 0;
for (int i = 0; i < MAX_POINTERS; i++) {
// Check whether the button should be hot
if (UIRegionHit(i, x, y, w, h, 0)) {
uistate.hotitem[i] = id;
if (uistate.activeitem[i] == 0 && uistate.mousedown[i])
uistate.activeitem[i] = id;
}
int clicked = 0;
// If button is hot and active, but mouse button is not
// down, the user must have clicked the button.
if (uistate.mousedown[i] == 0 &&
uistate.hotitem[i] == id &&
uistate.activeitem[i] == id &&
state->selected != -1) {
clicked = 1;
}
}
for (int i = 0; i < MAX_POINTERS; i++) {
// Check whether the button should be hot
if (UIRegionHit(i, x, y, w, h, 0)) {
uistate.hotitem[i] = id;
if (uistate.activeitem[i] == 0 && uistate.mousedown[i])
uistate.activeitem[i] = id;
}
// render items
int itemHeight = adapter->itemHeight(0);
int numItems = adapter->getCount();
for (int i = 0; i < numItems; i++) {
int item_y = y + i * itemHeight - state->scrollY;
if (uistate.mousedown && adapter->itemEnabled(i) && item_y >= y - itemHeight && item_y <= y + h &&
UIRegionHit(i, x, item_y, w, h, 0)) {
// ultra fast touch response
state->selected = i;
}
adapter->drawItem(i, x, item_y, w, itemHeight, i == state->selected);
}
uistate.lastwidget = id;
// If button is hot and active, but mouse button is not
// down, the user must have clicked the button.
if (uistate.mousedown[i] == 0 &&
uistate.hotitem[i] == id &&
uistate.activeitem[i] == id &&
state->selected != -1) {
clicked = 1;
}
}
// Otherwise, no clicky.
// render items
int itemHeight = adapter->itemHeight(0);
int numItems = adapter->getCount();
for (int i = 0; i < numItems; i++) {
int item_y = y + i * itemHeight - state->scrollY;
if (uistate.mousedown && adapter->itemEnabled(i) && item_y >= y - itemHeight && item_y <= y + h &&
UIRegionHit(i, x, item_y, w, h, 0)) {
// ultra fast touch response
state->selected = i;
}
adapter->drawItem(i, x, item_y, w, itemHeight, i == state->selected);
}
uistate.lastwidget = id;
// Otherwise, no clicky.
return clicked;
}
/*
struct SlideItem {
const char *text;
int image;
uint32_t bgColor;
const char *text;
int image;
uint32_t bgColor;
};
struct SlideState
{
float scroll;
float scroll;
};
@@ -306,29 +315,29 @@ int UIHSlider(int id, int x, int y, int w, int max, int *value) {
// Calculate mouse cursor's relative y offset
int xpos = ((256 - 16) * *value) / max;
for (int i = 0; i < MAX_POINTERS; i++) {
// Check for hotness
if (UIRegionHit(i, x+8, y+8, 16, 255, 0)) {
uistate.hotitem[i] = id;
if (uistate.activeitem[i] == 0 && uistate.mousedown[i])
uistate.activeitem[i] = id;
}
for (int i = 0; i < MAX_POINTERS; i++) {
// Check for hotness
if (UIRegionHit(i, x+8, y+8, 16, 255, 0)) {
uistate.hotitem[i] = id;
if (uistate.activeitem[i] == 0 && uistate.mousedown[i])
uistate.activeitem[i] = id;
}
// Update widget value
if (uistate.activeitem[i] == id) {
int mousepos = uistate.mousey[i] - (y + 8);
if (mousepos < 0) mousepos = 0;
if (mousepos > 255) mousepos = 255;
int v = (mousepos * max) / 255;
if (v != *value) {
*value = v;
return 1;
}
}
}
// Update widget value
if (uistate.activeitem[i] == id) {
int mousepos = uistate.mousey[i] - (y + 8);
if (mousepos < 0) mousepos = 0;
if (mousepos > 255) mousepos = 255;
int v = (mousepos * max) / 255;
if (v != *value) {
*value = v;
return 1;
}
}
}
// Render the scrollbar
ui_draw2d.Rect(x, y, 32, 256+16, 0x777777);
ui_draw2d.Rect(x+8+xpos, y+8, 16, 16, 0xffffff);
return 0;
+59 -52
View File
@@ -27,49 +27,52 @@
class LayoutManager {
public:
virtual void GetPos(float *w, float *h, float *x, float *y) const = 0;
virtual void GetPos(float *w, float *h, float *x, float *y) const = 0;
};
class Pos : public LayoutManager {
public:
Pos(float x, float y) : x_(x), y_(y) {}
virtual void GetPos(float *w, float *h, float *x, float *y) const {
*x = x_;
*y = y_;
}
Pos(float x, float y) : x_(x), y_(y) {}
virtual void GetPos(float *w, float *h, float *x, float *y) const {
*x = x_;
*y = y_;
}
private:
float x_;
float y_;
float x_;
float y_;
};
class HLinear : public LayoutManager {
public:
HLinear(float x, float y, float spacing = 2.0f) : x_(x), y_(y), spacing_(spacing) {}
virtual void GetPos(float *w, float *h, float *x, float *y) const {
*x = x_;
*y = y_;
x_ += *w + spacing_;
}
HLinear(float x, float y, float spacing = 2.0f) : x_(x), y_(y), spacing_(spacing) {}
virtual void GetPos(float *w, float *h, float *x, float *y) const {
*x = x_;
*y = y_;
x_ += *w + spacing_;
}
void Space(float x) {
x_ += x;
}
private:
mutable float x_;
float y_;
float spacing_;
mutable float x_;
float y_;
float spacing_;
};
class VLinear : public LayoutManager {
public:
VLinear(float x, float y, float spacing = 2.0f) : x_(x), y_(y), spacing_(spacing) {}
virtual void GetPos(float *w, float *h, float *x, float *y) const {
*x = x_;
*y = y_;
y_ += *h + spacing_;
}
VLinear(float x, float y, float spacing = 2.0f) : x_(x), y_(y), spacing_(spacing) {}
virtual void GetPos(float *w, float *h, float *x, float *y) const {
*x = x_;
*y = y_;
y_ += *h + spacing_;
}
private:
float x_;
mutable float y_;
float spacing_;
float x_;
mutable float y_;
float spacing_;
};
#ifndef MAX_POINTERS
@@ -78,25 +81,29 @@ private:
// Mouse out of habit, applies just as well to touch events.
// UI does not yet support multitouch.
// This struct is zeroed on init, so should be valid at that state.
struct UIState {
int mousex[MAX_POINTERS];
int mousey[MAX_POINTERS];
int mousedown[MAX_POINTERS];
int mousepressed[MAX_POINTERS];
bool mousedown[MAX_POINTERS];
bool mousepressed[MAX_POINTERS];
short mouseframesdown[MAX_POINTERS];
int mouseStartX[MAX_POINTERS];
int mouseStartY[MAX_POINTERS];
int mouseStartX[MAX_POINTERS];
int mouseStartY[MAX_POINTERS];
int hotitem[MAX_POINTERS];
int hotitem[MAX_POINTERS];
int activeitem[MAX_POINTERS];
// keyboard focus, not currently used
int kbdwidget;
int lastwidget;
// keyboard focus, not currently used
int kbdwidget;
int lastwidget;
// Used by controls that need to keep track of the initial value for drags, for example.
// Should probably be indexed by finger - would be neat to be able to move two knobs at the same time.
float tempfloat;
// Used by controls that need to keep track of the initial value for drags, for example.
// Should probably be indexed by finger - would be neat to be able to move two knobs at the same time.
float tempfloat;
int ui_tick;
};
// This needs to be extern so that additional UI controls can be developed outside this file.
@@ -118,38 +125,38 @@ const int LARGE_BUTTON_WIDTH = 192;
const int BUTTON_HEIGHT = 72;
struct SlideItem {
const char *text;
int image;
uint32_t bgColor;
const char *text;
int image;
uint32_t bgColor;
};
struct UISlideState {
float scroll;
float scroll;
};
// Implement this interface to style your lists
class UIListAdapter {
public:
virtual size_t getCount() const = 0;
virtual void drawItem(int item, int x, int y, int w, int h, bool active) const = 0;
virtual float itemHeight(int itemIndex) const { return 64; }
virtual bool itemEnabled(int itemIndex) const { return true; }
virtual size_t getCount() const = 0;
virtual void drawItem(int item, int x, int y, int w, int h, bool active) const = 0;
virtual float itemHeight(int itemIndex) const { return 64; }
virtual bool itemEnabled(int itemIndex) const { return true; }
};
class StringVectorListAdapter : public UIListAdapter {
public:
StringVectorListAdapter(std::vector<std::string> *items) : items_(items) {}
virtual size_t getCount() const { return items_->size(); }
virtual void drawItem(int item, int x, int y, int w, int h, bool active) const;
StringVectorListAdapter(std::vector<std::string> *items) : items_(items) {}
virtual size_t getCount() const { return items_->size(); }
virtual void drawItem(int item, int x, int y, int w, int h, bool active) const;
private:
std::vector<std::string> *items_;
std::vector<std::string> *items_;
};
struct UIListState {
UIListState() : scrollY(0.0f), selected(-1) {}
float scrollY;
int selected;
UIListState() : scrollY(0.0f), selected(-1) {}
float scrollY;
int selected;
};
+23
View File
@@ -37,6 +37,29 @@ inline uint32_t _rotr(uint32_t val, int shift) {
return (val << shift) | (val >> (31 - shift));
}
/*
template <int SZ>
class BitArray {
public:
BitArray() {
memset(data, 0, sizeof(data));
}
BitArray And(const BitArray &other) {
BitArray<SZ> retVal;
for (int i = 0; i < DATACOUNT; i++) {
retVal.data[i] = data[i] & other.data[i];
}
}
private:
uint32 data[(SZ + 31) / 32];
enum {
DATACOUNT = (SZ + 31) / 32;
};
};
*/
#endif
#endif