summaryrefslogtreecommitdiff
path: root/src/shared
diff options
context:
space:
mode:
Diffstat (limited to 'src/shared')
-rw-r--r--src/shared/command.h378
-rw-r--r--src/shared/crypto.cpp1630
-rw-r--r--src/shared/cube.h32
-rw-r--r--src/shared/cube2font.c876
-rw-r--r--src/shared/ents.h328
-rw-r--r--src/shared/geom.cpp444
-rw-r--r--src/shared/geom.h3202
-rw-r--r--src/shared/glemu.cpp692
-rw-r--r--src/shared/glemu.h352
-rw-r--r--src/shared/glexts.h485
-rw-r--r--src/shared/iengine.h318
-rw-r--r--src/shared/igame.h218
-rw-r--r--src/shared/stream.cpp2012
-rw-r--r--src/shared/tools.cpp276
-rw-r--r--src/shared/tools.h1878
-rw-r--r--src/shared/zip.cpp994
16 files changed, 6915 insertions, 7200 deletions
diff --git a/src/shared/command.h b/src/shared/command.h
index c07dee8..ffb2115 100644
--- a/src/shared/command.h
+++ b/src/shared/command.h
@@ -4,38 +4,38 @@ enum { VAL_NULL = 0, VAL_INT, VAL_FLOAT, VAL_STR, VAL_ANY, VAL_CODE, VAL_MACRO,
enum
{
- CODE_START = 0,
- CODE_OFFSET,
- CODE_POP,
- CODE_ENTER,
- CODE_EXIT,
- CODE_VAL,
- CODE_VALI,
- CODE_MACRO,
- CODE_BOOL,
- CODE_BLOCK,
- CODE_COMPILE,
- CODE_FORCE,
- CODE_RESULT,
- CODE_IDENT, CODE_IDENTU, CODE_IDENTARG,
- CODE_COM, CODE_COMD, CODE_COMC, CODE_COMV,
- CODE_CONC, CODE_CONCW, CODE_CONCM, CODE_DOWN,
- CODE_SVAR, CODE_SVAR1,
- CODE_IVAR, CODE_IVAR1, CODE_IVAR2, CODE_IVAR3,
- CODE_FVAR, CODE_FVAR1,
- CODE_LOOKUP, CODE_LOOKUPU, CODE_LOOKUPARG, CODE_ALIAS, CODE_ALIASU, CODE_ALIASARG, CODE_CALL, CODE_CALLU, CODE_CALLARG,
- CODE_PRINT,
- CODE_LOCAL,
-
- CODE_OP_MASK = 0x3F,
- CODE_RET = 6,
- CODE_RET_MASK = 0xC0,
-
- /* return type flags */
- RET_NULL = VAL_NULL<<CODE_RET,
- RET_STR = VAL_STR<<CODE_RET,
- RET_INT = VAL_INT<<CODE_RET,
- RET_FLOAT = VAL_FLOAT<<CODE_RET,
+ CODE_START = 0,
+ CODE_OFFSET,
+ CODE_POP,
+ CODE_ENTER,
+ CODE_EXIT,
+ CODE_VAL,
+ CODE_VALI,
+ CODE_MACRO,
+ CODE_BOOL,
+ CODE_BLOCK,
+ CODE_COMPILE,
+ CODE_FORCE,
+ CODE_RESULT,
+ CODE_IDENT, CODE_IDENTU, CODE_IDENTARG,
+ CODE_COM, CODE_COMD, CODE_COMC, CODE_COMV,
+ CODE_CONC, CODE_CONCW, CODE_CONCM, CODE_DOWN,
+ CODE_SVAR, CODE_SVAR1,
+ CODE_IVAR, CODE_IVAR1, CODE_IVAR2, CODE_IVAR3,
+ CODE_FVAR, CODE_FVAR1,
+ CODE_LOOKUP, CODE_LOOKUPU, CODE_LOOKUPARG, CODE_ALIAS, CODE_ALIASU, CODE_ALIASARG, CODE_CALL, CODE_CALLU, CODE_CALLARG,
+ CODE_PRINT,
+ CODE_LOCAL,
+
+ CODE_OP_MASK = 0x3F,
+ CODE_RET = 6,
+ CODE_RET_MASK = 0xC0,
+
+ /* return type flags */
+ RET_NULL = VAL_NULL<<CODE_RET,
+ RET_STR = VAL_STR<<CODE_RET,
+ RET_INT = VAL_INT<<CODE_RET,
+ RET_FLOAT = VAL_FLOAT<<CODE_RET,
};
enum { ID_VAR, ID_FVAR, ID_SVAR, ID_COMMAND, ID_ALIAS, ID_LOCAL };
@@ -46,147 +46,147 @@ struct ident;
struct identval
{
- union
- {
- int i; // ID_VAR, VAL_INT
- float f; // ID_FVAR, VAL_FLOAT
- char *s; // ID_SVAR, VAL_STR
- const uint *code; // VAL_CODE
- ident *id; // VAL_IDENT
- };
+ union
+ {
+ int i; // ID_VAR, VAL_INT
+ float f; // ID_FVAR, VAL_FLOAT
+ char *s; // ID_SVAR, VAL_STR
+ const uint *code; // VAL_CODE
+ ident *id; // VAL_IDENT
+ };
};
struct tagval : identval
{
- int type;
-
- void setint(int val) { type = VAL_INT; i = val; }
- void setfloat(float val) { type = VAL_FLOAT; f = val; }
- void setstr(char *val) { type = VAL_STR; s = val; }
- void setnull() { type = VAL_NULL; i = 0; }
- void setcode(const uint *val) { type = VAL_CODE; code = val; }
- void setmacro(const uint *val) { type = VAL_MACRO; code = val; }
- void setident(ident *val) { type = VAL_IDENT; id = val; }
-
- const char *getstr() const;
- int getint() const;
- float getfloat() const;
- bool getbool() const;
-
- void cleanup();
+ int type;
+
+ void setint(int val) { type = VAL_INT; i = val; }
+ void setfloat(float val) { type = VAL_FLOAT; f = val; }
+ void setstr(char *val) { type = VAL_STR; s = val; }
+ void setnull() { type = VAL_NULL; i = 0; }
+ void setcode(const uint *val) { type = VAL_CODE; code = val; }
+ void setmacro(const uint *val) { type = VAL_MACRO; code = val; }
+ void setident(ident *val) { type = VAL_IDENT; id = val; }
+
+ const char *getstr() const;
+ int getint() const;
+ float getfloat() const;
+ bool getbool() const;
+
+ void cleanup();
};
struct identstack
{
- identval val;
- int valtype;
- identstack *next;
+ identval val;
+ int valtype;
+ identstack *next;
};
union identvalptr
{
- int *i; // ID_VAR
- float *f; // ID_FVAR
- char **s; // ID_SVAR
+ int *i; // ID_VAR
+ float *f; // ID_FVAR
+ char **s; // ID_SVAR
};
typedef void (__cdecl *identfun)();
struct ident
{
- uchar type; // one of ID_* above
- union
- {
- uchar valtype; // ID_ALIAS
- uchar numargs; // ID_COMMAND
- };
- ushort flags;
- int index;
- const char *name;
- union
- {
- struct // ID_VAR, ID_FVAR, ID_SVAR
- {
- union
- {
- struct { int minval, maxval; }; // ID_VAR
- struct { float minvalf, maxvalf; }; // ID_FVAR
- };
- identvalptr storage;
- identval overrideval;
- };
- struct // ID_ALIAS
- {
- uint *code;
- identval val;
- identstack *stack;
- };
- struct // ID_COMMAND
- {
- const char *args;
- uint argmask;
- };
- };
- identfun fun; // ID_VAR, ID_FVAR, ID_SVAR, ID_COMMAND
-
- ident() {}
- // ID_VAR
- ident(int t, const char *n, int m, int x, int *s, void *f = NULL, int flags = 0)
- : type(t), flags(flags | (m > x ? IDF_READONLY : 0)), name(n), minval(m), maxval(x), fun((identfun)f)
- { storage.i = s; }
- // ID_FVAR
- ident(int t, const char *n, float m, float x, float *s, void *f = NULL, int flags = 0)
- : type(t), flags(flags | (m > x ? IDF_READONLY : 0)), name(n), minvalf(m), maxvalf(x), fun((identfun)f)
- { storage.f = s; }
- // ID_SVAR
- ident(int t, const char *n, char **s, void *f = NULL, int flags = 0)
- : type(t), flags(flags), name(n), fun((identfun)f)
- { storage.s = s; }
- // ID_ALIAS
- ident(int t, const char *n, char *a, int flags)
- : type(t), valtype(VAL_STR), flags(flags), name(n), code(NULL), stack(NULL)
- { val.s = a; }
- ident(int t, const char *n, int a, int flags)
- : type(t), valtype(VAL_INT), flags(flags), name(n), code(NULL), stack(NULL)
- { val.i = a; }
- ident(int t, const char *n, float a, int flags)
- : type(t), valtype(VAL_FLOAT), flags(flags), name(n), code(NULL), stack(NULL)
- { val.f = a; }
- ident(int t, const char *n, int flags)
- : type(t), valtype(VAL_NULL), flags(flags), name(n), code(NULL), stack(NULL)
- {}
- ident(int t, const char *n, const tagval &v, int flags)
- : type(t), valtype(v.type), flags(flags), name(n), code(NULL), stack(NULL)
- { val = v; }
- // ID_COMMAND
- ident(int t, const char *n, const char *args, uint argmask, int numargs, void *f = NULL, int flags = 0)
- : type(t), numargs(numargs), flags(flags), name(n), args(args), argmask(argmask), fun((identfun)f)
- {}
-
- void changed() { if(fun) fun(); }
-
- void setval(const tagval &v)
- {
- valtype = v.type;
- val = v;
- }
-
- void setval(const identstack &v)
- {
- valtype = v.valtype;
- val = v.val;
- }
-
- void forcenull()
- {
- if(valtype==VAL_STR) delete[] val.s;
- valtype = VAL_NULL;
- }
-
- float getfloat() const;
- int getint() const;
- const char *getstr() const;
- void getval(tagval &v) const;
+ uchar type; // one of ID_* above
+ union
+ {
+ uchar valtype; // ID_ALIAS
+ uchar numargs; // ID_COMMAND
+ };
+ ushort flags;
+ int index;
+ const char *name;
+ union
+ {
+ struct // ID_VAR, ID_FVAR, ID_SVAR
+ {
+ union
+ {
+ struct { int minval, maxval; }; // ID_VAR
+ struct { float minvalf, maxvalf; }; // ID_FVAR
+ };
+ identvalptr storage;
+ identval overrideval;
+ };
+ struct // ID_ALIAS
+ {
+ uint *code;
+ identval val;
+ identstack *stack;
+ };
+ struct // ID_COMMAND
+ {
+ const char *args;
+ uint argmask;
+ };
+ };
+ identfun fun; // ID_VAR, ID_FVAR, ID_SVAR, ID_COMMAND
+
+ ident() {}
+ // ID_VAR
+ ident(int t, const char *n, int m, int x, int *s, void *f = NULL, int flags = 0)
+ : type(t), flags(flags | (m > x ? IDF_READONLY : 0)), name(n), minval(m), maxval(x), fun((identfun)f)
+ { storage.i = s; }
+ // ID_FVAR
+ ident(int t, const char *n, float m, float x, float *s, void *f = NULL, int flags = 0)
+ : type(t), flags(flags | (m > x ? IDF_READONLY : 0)), name(n), minvalf(m), maxvalf(x), fun((identfun)f)
+ { storage.f = s; }
+ // ID_SVAR
+ ident(int t, const char *n, char **s, void *f = NULL, int flags = 0)
+ : type(t), flags(flags), name(n), fun((identfun)f)
+ { storage.s = s; }
+ // ID_ALIAS
+ ident(int t, const char *n, char *a, int flags)
+ : type(t), valtype(VAL_STR), flags(flags), name(n), code(NULL), stack(NULL)
+ { val.s = a; }
+ ident(int t, const char *n, int a, int flags)
+ : type(t), valtype(VAL_INT), flags(flags), name(n), code(NULL), stack(NULL)
+ { val.i = a; }
+ ident(int t, const char *n, float a, int flags)
+ : type(t), valtype(VAL_FLOAT), flags(flags), name(n), code(NULL), stack(NULL)
+ { val.f = a; }
+ ident(int t, const char *n, int flags)
+ : type(t), valtype(VAL_NULL), flags(flags), name(n), code(NULL), stack(NULL)
+ {}
+ ident(int t, const char *n, const tagval &v, int flags)
+ : type(t), valtype(v.type), flags(flags), name(n), code(NULL), stack(NULL)
+ { val = v; }
+ // ID_COMMAND
+ ident(int t, const char *n, const char *args, uint argmask, int numargs, void *f = NULL, int flags = 0)
+ : type(t), numargs(numargs), flags(flags), name(n), args(args), argmask(argmask), fun((identfun)f)
+ {}
+
+ void changed() { if(fun) fun(); }
+
+ void setval(const tagval &v)
+ {
+ valtype = v.type;
+ val = v;
+ }
+
+ void setval(const identstack &v)
+ {
+ valtype = v.valtype;
+ val = v.val;
+ }
+
+ void forcenull()
+ {
+ if(valtype==VAL_STR) delete[] val.s;
+ valtype = VAL_NULL;
+ }
+
+ float getfloat() const;
+ int getint() const;
+ const char *getstr() const;
+ void getval(tagval &v) const;
};
extern void addident(ident *id);
@@ -202,15 +202,15 @@ extern void result(const char *s);
static inline int parseint(const char *s)
{
- return int(strtoul(s, NULL, 0));
+ return int(strtoul(s, NULL, 0));
}
static inline float parsefloat(const char *s)
{
- // not all platforms (windows) can parse hexadecimal integers via strtod
- char *end;
- double val = strtod(s, &end);
- return val || end==s || (*end!='x' && *end!='X') ? float(val) : float(parseint(s));
+ // not all platforms (windows) can parse hexadecimal integers via strtod
+ char *end;
+ double val = strtod(s, &end);
+ return val || end==s || (*end!='x' && *end!='X') ? float(val) : float(parseint(s));
}
static inline void intformat(char *buf, int v, int len = 20) { nformatstring(buf, len, "%d", v); }
@@ -218,52 +218,52 @@ static inline void floatformat(char *buf, float v, int len = 20) { nformatstring
static inline const char *getstr(const identval &v, int type)
{
- switch(type)
- {
- case VAL_STR: case VAL_MACRO: return v.s;
- case VAL_INT: return intstr(v.i);
- case VAL_FLOAT: return floatstr(v.f);
- default: return "";
- }
+ switch(type)
+ {
+ case VAL_STR: case VAL_MACRO: return v.s;
+ case VAL_INT: return intstr(v.i);
+ case VAL_FLOAT: return floatstr(v.f);
+ default: return "";
+ }
}
inline const char *tagval::getstr() const { return ::getstr(*this, type); }
inline const char *ident::getstr() const { return ::getstr(val, valtype); }
static inline int getint(const identval &v, int type)
{
- switch(type)
- {
- case VAL_INT: return v.i;
- case VAL_FLOAT: return int(v.f);
- case VAL_STR: case VAL_MACRO: return parseint(v.s);
- default: return 0;
- }
+ switch(type)
+ {
+ case VAL_INT: return v.i;
+ case VAL_FLOAT: return int(v.f);
+ case VAL_STR: case VAL_MACRO: return parseint(v.s);
+ default: return 0;
+ }
}
inline int tagval::getint() const { return ::getint(*this, type); }
inline int ident::getint() const { return ::getint(val, valtype); }
static inline float getfloat(const identval &v, int type)
{
- switch(type)
- {
- case VAL_FLOAT: return v.f;
- case VAL_INT: return float(v.i);
- case VAL_STR: case VAL_MACRO: return parsefloat(v.s);
- default: return 0.0f;
- }
+ switch(type)
+ {
+ case VAL_FLOAT: return v.f;
+ case VAL_INT: return float(v.i);
+ case VAL_STR: case VAL_MACRO: return parsefloat(v.s);
+ default: return 0.0f;
+ }
}
inline float tagval::getfloat() const { return ::getfloat(*this, type); }
inline float ident::getfloat() const { return ::getfloat(val, valtype); }
inline void ident::getval(tagval &v) const
{
- switch(valtype)
- {
- case VAL_STR: case VAL_MACRO: v.setstr(newstring(val.s)); break;
- case VAL_INT: v.setint(val.i); break;
- case VAL_FLOAT: v.setfloat(val.f); break;
- default: v.setnull(); break;
- }
+ switch(valtype)
+ {
+ case VAL_STR: case VAL_MACRO: v.setstr(newstring(val.s)); break;
+ case VAL_INT: v.setint(val.i); break;
+ case VAL_FLOAT: v.setfloat(val.f); break;
+ default: v.setnull(); break;
+ }
}
// nasty macros for registering script functions, abuses globals to avoid excessive infrastructure
@@ -326,7 +326,7 @@ inline void ident::getval(tagval &v) const
// anonymous inline commands, uses nasty template trick with line numbers to keep names unique
#define ICOMMANDNS(name, cmdname, nargs, proto, b) template<int N> struct cmdname; template<> struct cmdname<__LINE__> { static bool init; static void run proto; }; bool cmdname<__LINE__>::init = addcommand(name, (identfun)cmdname<__LINE__>::run, nargs); void cmdname<__LINE__>::run proto \
- { b; }
+ { b; }
#define ICOMMANDN(name, cmdname, nargs, proto, b) ICOMMANDNS(#name, cmdname, nargs, proto, b)
#define ICOMMANDNAME(name) _icmd_##name
#define ICOMMAND(name, nargs, proto, b) ICOMMANDN(name, ICOMMANDNAME(name), nargs, proto, b)
diff --git a/src/shared/crypto.cpp b/src/shared/crypto.cpp
index 72dea47..fd0a950 100644
--- a/src/shared/crypto.cpp
+++ b/src/shared/crypto.cpp
@@ -11,42 +11,42 @@
namespace tiger
{
- typedef unsigned long long int chunk;
-
- union hashval
- {
- uchar bytes[3*8];
- chunk chunks[3];
- };
-
- chunk sboxes[4*256];
-
- void compress(const chunk *str, chunk state[3])
- {
- chunk a, b, c;
- chunk aa, bb, cc;
- chunk x0, x1, x2, x3, x4, x5, x6, x7;
-
- a = state[0];
- b = state[1];
- c = state[2];
-
- x0=str[0]; x1=str[1]; x2=str[2]; x3=str[3];
- x4=str[4]; x5=str[5]; x6=str[6]; x7=str[7];
-
- aa = a;
- bb = b;
- cc = c;
-
- loop(pass_no, TIGER_PASSES)
- {
- if(pass_no)
- {
- x0 -= x7 ^ 0xA5A5A5A5A5A5A5A5ULL; x1 ^= x0; x2 += x1; x3 -= x2 ^ ((~x1)<<19);
- x4 ^= x3; x5 += x4; x6 -= x5 ^ ((~x4)>>23); x7 ^= x6;
- x0 += x7; x1 -= x0 ^ ((~x7)<<19); x2 ^= x1; x3 += x2;
- x4 -= x3 ^ ((~x2)>>23); x5 ^= x4; x6 += x5; x7 -= x6 ^ 0x0123456789ABCDEFULL;
- }
+ typedef unsigned long long int chunk;
+
+ union hashval
+ {
+ uchar bytes[3*8];
+ chunk chunks[3];
+ };
+
+ chunk sboxes[4*256];
+
+ void compress(const chunk *str, chunk state[3])
+ {
+ chunk a, b, c;
+ chunk aa, bb, cc;
+ chunk x0, x1, x2, x3, x4, x5, x6, x7;
+
+ a = state[0];
+ b = state[1];
+ c = state[2];
+
+ x0=str[0]; x1=str[1]; x2=str[2]; x3=str[3];
+ x4=str[4]; x5=str[5]; x6=str[6]; x7=str[7];
+
+ aa = a;
+ bb = b;
+ cc = c;
+
+ loop(pass_no, TIGER_PASSES)
+ {
+ if(pass_no)
+ {
+ x0 -= x7 ^ 0xA5A5A5A5A5A5A5A5ULL; x1 ^= x0; x2 += x1; x3 -= x2 ^ ((~x1)<<19);
+ x4 ^= x3; x5 += x4; x6 -= x5 ^ ((~x4)>>23); x7 ^= x6;
+ x0 += x7; x1 -= x0 ^ ((~x7)<<19); x2 ^= x1; x3 += x2;
+ x4 -= x3 ^ ((~x2)>>23); x5 ^= x4; x6 += x5; x7 -= x6 ^ 0x0123456789ABCDEFULL;
+ }
#define sb1 (sboxes)
#define sb2 (sboxes+256)
@@ -54,107 +54,107 @@ namespace tiger
#define sb4 (sboxes+256*3)
#define round(a, b, c, x) \
- c ^= x; \
- a -= sb1[((c)>>(0*8))&0xFF] ^ sb2[((c)>>(2*8))&0xFF] ^ \
- sb3[((c)>>(4*8))&0xFF] ^ sb4[((c)>>(6*8))&0xFF] ; \
- b += sb4[((c)>>(1*8))&0xFF] ^ sb3[((c)>>(3*8))&0xFF] ^ \
- sb2[((c)>>(5*8))&0xFF] ^ sb1[((c)>>(7*8))&0xFF] ; \
- b *= mul;
-
- uint mul = !pass_no ? 5 : (pass_no==1 ? 7 : 9);
- round(a, b, c, x0) round(b, c, a, x1) round(c, a, b, x2) round(a, b, c, x3)
- round(b, c, a, x4) round(c, a, b, x5) round(a, b, c, x6) round(b, c, a, x7)
-
- chunk tmp = a; a = c; c = b; b = tmp;
- }
-
- a ^= aa;
- b -= bb;
- c += cc;
-
- state[0] = a;
- state[1] = b;
- state[2] = c;
- }
-
- void gensboxes()
- {
- const char *str = "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham";
- chunk state[3] = { 0x0123456789ABCDEFULL, 0xFEDCBA9876543210ULL, 0xF096A5B4C3B2E187ULL };
- uchar temp[64];
-
- if(!*(const uchar *)&islittleendian) loopj(64) temp[j^7] = str[j];
- else loopj(64) temp[j] = str[j];
- loopi(1024) loop(col, 8) ((uchar *)&sboxes[i])[col] = i&0xFF;
-
- int abc = 2;
- loop(pass, 5) loopi(256) for(int sb = 0; sb < 1024; sb += 256)
- {
- abc++;
- if(abc >= 3) { abc = 0; compress((chunk *)temp, state); }
- loop(col, 8)
- {
- uchar val = ((uchar *)&sboxes[sb+i])[col];
- ((uchar *)&sboxes[sb+i])[col] = ((uchar *)&sboxes[sb + ((uchar *)&state[abc])[col]])[col];
- ((uchar *)&sboxes[sb + ((uchar *)&state[abc])[col]])[col] = val;
- }
- }
- }
-
- void hash(const uchar *str, int length, hashval &val)
- {
- static bool init = false;
- if(!init) { gensboxes(); init = true; }
-
- uchar temp[65];
-
- val.chunks[0] = 0x0123456789ABCDEFULL;
- val.chunks[1] = 0xFEDCBA9876543210ULL;
- val.chunks[2] = 0xF096A5B4C3B2E187ULL;
-
- int i = length;
- for(; i >= 64; i -= 64, str += 64)
- {
- if(!*(const uchar *)&islittleendian)
- {
- loopj(64) temp[j^7] = str[j];
- compress((chunk *)temp, val.chunks);
- }
- else compress((chunk *)str, val.chunks);
- }
-
- int j;
- if(!*(const uchar *)&islittleendian)
- {
- for(j = 0; j < i; j++) temp[j^7] = str[j];
- temp[j^7] = 0x01;
- while(++j&7) temp[j^7] = 0;
- }
- else
- {
- for(j = 0; j < i; j++) temp[j] = str[j];
- temp[j] = 0x01;
- while(++j&7) temp[j] = 0;
- }
-
- if(j > 56)
- {
- while(j < 64) temp[j++] = 0;
- compress((chunk *)temp, val.chunks);
- j = 0;
- }
- while(j < 56) temp[j++] = 0;
- *(chunk *)(temp+56) = (chunk)length<<3;
- compress((chunk *)temp, val.chunks);
- if(!*(const uchar *)&islittleendian)
- {
- loopk(3)
- {
- uchar *c = &val.bytes[k*sizeof(chunk)];
- loopl(sizeof(chunk)/2) swap(c[l], c[sizeof(chunk)-1-l]);
- }
- }
- }
+ c ^= x; \
+ a -= sb1[((c)>>(0*8))&0xFF] ^ sb2[((c)>>(2*8))&0xFF] ^ \
+ sb3[((c)>>(4*8))&0xFF] ^ sb4[((c)>>(6*8))&0xFF] ; \
+ b += sb4[((c)>>(1*8))&0xFF] ^ sb3[((c)>>(3*8))&0xFF] ^ \
+ sb2[((c)>>(5*8))&0xFF] ^ sb1[((c)>>(7*8))&0xFF] ; \
+ b *= mul;
+
+ uint mul = !pass_no ? 5 : (pass_no==1 ? 7 : 9);
+ round(a, b, c, x0) round(b, c, a, x1) round(c, a, b, x2) round(a, b, c, x3)
+ round(b, c, a, x4) round(c, a, b, x5) round(a, b, c, x6) round(b, c, a, x7)
+
+ chunk tmp = a; a = c; c = b; b = tmp;
+ }
+
+ a ^= aa;
+ b -= bb;
+ c += cc;
+
+ state[0] = a;
+ state[1] = b;
+ state[2] = c;
+ }
+
+ void gensboxes()
+ {
+ const char *str = "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham";
+ chunk state[3] = { 0x0123456789ABCDEFULL, 0xFEDCBA9876543210ULL, 0xF096A5B4C3B2E187ULL };
+ uchar temp[64];
+
+ if(!*(const uchar *)&islittleendian) loopj(64) temp[j^7] = str[j];
+ else loopj(64) temp[j] = str[j];
+ loopi(1024) loop(col, 8) ((uchar *)&sboxes[i])[col] = i&0xFF;
+
+ int abc = 2;
+ loop(pass, 5) loopi(256) for(int sb = 0; sb < 1024; sb += 256)
+ {
+ abc++;
+ if(abc >= 3) { abc = 0; compress((chunk *)temp, state); }
+ loop(col, 8)
+ {
+ uchar val = ((uchar *)&sboxes[sb+i])[col];
+ ((uchar *)&sboxes[sb+i])[col] = ((uchar *)&sboxes[sb + ((uchar *)&state[abc])[col]])[col];
+ ((uchar *)&sboxes[sb + ((uchar *)&state[abc])[col]])[col] = val;
+ }
+ }
+ }
+
+ void hash(const uchar *str, int length, hashval &val)
+ {
+ static bool init = false;
+ if(!init) { gensboxes(); init = true; }
+
+ uchar temp[65];
+
+ val.chunks[0] = 0x0123456789ABCDEFULL;
+ val.chunks[1] = 0xFEDCBA9876543210ULL;
+ val.chunks[2] = 0xF096A5B4C3B2E187ULL;
+
+ int i = length;
+ for(; i >= 64; i -= 64, str += 64)
+ {
+ if(!*(const uchar *)&islittleendian)
+ {
+ loopj(64) temp[j^7] = str[j];
+ compress((chunk *)temp, val.chunks);
+ }
+ else compress((chunk *)str, val.chunks);
+ }
+
+ int j;
+ if(!*(const uchar *)&islittleendian)
+ {
+ for(j = 0; j < i; j++) temp[j^7] = str[j];
+ temp[j^7] = 0x01;
+ while(++j&7) temp[j^7] = 0;
+ }
+ else
+ {
+ for(j = 0; j < i; j++) temp[j] = str[j];
+ temp[j] = 0x01;
+ while(++j&7) temp[j] = 0;
+ }
+
+ if(j > 56)
+ {
+ while(j < 64) temp[j++] = 0;
+ compress((chunk *)temp, val.chunks);
+ j = 0;
+ }
+ while(j < 56) temp[j++] = 0;
+ *(chunk *)(temp+56) = (chunk)length<<3;
+ compress((chunk *)temp, val.chunks);
+ if(!*(const uchar *)&islittleendian)
+ {
+ loopk(3)
+ {
+ uchar *c = &val.bytes[k*sizeof(chunk)];
+ loopl(sizeof(chunk)/2) swap(c[l], c[sizeof(chunk)-1-l]);
+ }
+ }
+ }
}
/* Elliptic curve cryptography based on NIST DSS prime curves. */
@@ -164,254 +164,254 @@ namespace tiger
template<int BI_DIGITS> struct bigint
{
- typedef ushort digit;
- typedef uint dbldigit;
-
- int len;
- digit digits[BI_DIGITS];
-
- bigint() {}
- bigint(digit n) { if(n) { len = 1; digits[0] = n; } else len = 0; }
- bigint(const char *s) { parse(s); }
- template<int Y_DIGITS> bigint(const bigint<Y_DIGITS> &y) { *this = y; }
-
- static int parsedigits(ushort *digits, int maxlen, const char *s)
- {
- int slen = 0;
- while(isxdigit(s[slen])) slen++;
- int len = (slen+2*sizeof(ushort)-1)/(2*sizeof(ushort));
- if(len>maxlen) return 0;
- memset(digits, 0, len*sizeof(ushort));
- loopi(slen)
- {
- int c = s[slen-i-1];
- if(isalpha(c)) c = toupper(c) - 'A' + 10;
- else if(isdigit(c)) c -= '0';
- else return 0;
- digits[i/(2*sizeof(ushort))] |= c<<(4*(i%(2*sizeof(ushort))));
- }
- return len;
- }
-
- void parse(const char *s)
- {
- len = parsedigits(digits, BI_DIGITS, s);
- shrink();
- }
-
- void zero() { len = 0; }
-
- void print(stream *out) const
- {
- vector<char> buf;
- printdigits(buf);
- out->write(buf.getbuf(), buf.length());
- }
-
- void printdigits(vector<char> &buf) const
- {
- loopi(len)
- {
- digit d = digits[len-i-1];
- loopj(BI_DIGIT_BITS/4)
- {
- uint shift = BI_DIGIT_BITS - (j+1)*4;
- int val = (d >> shift) & 0xF;
- if(val < 10) buf.add('0' + val);
- else buf.add('a' + val - 10);
- }
- }
- }
-
- template<int Y_DIGITS> bigint &operator=(const bigint<Y_DIGITS> &y)
- {
- len = y.len;
- memcpy(digits, y.digits, len*sizeof(digit));
- return *this;
- }
-
- bool iszero() const { return !len; }
- bool isone() const { return len==1 && digits[0]==1; }
-
- int numbits() const
- {
- if(!len) return 0;
- int bits = len*BI_DIGIT_BITS;
- digit last = digits[len-1], mask = 1<<(BI_DIGIT_BITS-1);
- while(mask)
- {
- if(last&mask) return bits;
- bits--;
- mask >>= 1;
- }
- return 0;
- }
-
- bool hasbit(int n) const { return n/BI_DIGIT_BITS < len && ((digits[n/BI_DIGIT_BITS]>>(n%BI_DIGIT_BITS))&1); }
-
- bool morebits(int n) const { return len > n/BI_DIGIT_BITS; }
-
- template<int X_DIGITS, int Y_DIGITS> bigint &add(const bigint<X_DIGITS> &x, const bigint<Y_DIGITS> &y)
- {
- dbldigit carry = 0;
- int maxlen = max(x.len, y.len), i;
- for(i = 0; i < y.len || carry; i++)
- {
- carry += (i < x.len ? (dbldigit)x.digits[i] : 0) + (i < y.len ? (dbldigit)y.digits[i] : 0);
- digits[i] = (digit)carry;
- carry >>= BI_DIGIT_BITS;
- }
- if(i < x.len && this != &x) memcpy(&digits[i], &x.digits[i], (x.len - i)*sizeof(digit));
- len = max(i, maxlen);
- return *this;
- }
- template<int Y_DIGITS> bigint &add(const bigint<Y_DIGITS> &y) { return add(*this, y); }
-
- template<int X_DIGITS, int Y_DIGITS> bigint &sub(const bigint<X_DIGITS> &x, const bigint<Y_DIGITS> &y)
- {
- ASSERT(x >= y);
- dbldigit borrow = 0;
- int i;
- for(i = 0; i < y.len || borrow; i++)
- {
- borrow = (1<<BI_DIGIT_BITS) + (dbldigit)x.digits[i] - (i<y.len ? (dbldigit)y.digits[i] : 0) - borrow;
- digits[i] = (digit)borrow;
- borrow = (borrow>>BI_DIGIT_BITS)^1;
- }
- if(i < x.len && this != &x) memcpy(&digits[i], &x.digits[i], (x.len - i)*sizeof(digit));
- len = x.len;
- shrink();
- return *this;
- }
- template<int Y_DIGITS> bigint &sub(const bigint<Y_DIGITS> &y) { return sub(*this, y); }
-
- void shrink() { while(len > 0 && !digits[len-1]) len--; }
- void shrinkdigits(int n) { len = n; shrink(); }
- void shrinkbits(int n) { shrinkdigits(n/BI_DIGIT_BITS); }
-
- template<int Y_DIGITS> void copyshrinkdigits(const bigint<Y_DIGITS> &y, int n)
- {
- len = clamp(y.len, 0, n);
- memcpy(digits, y.digits, len*sizeof(digit));
- shrink();
- }
- template<int Y_DIGITS> void copyshrinkbits(const bigint<Y_DIGITS> &y, int n)
- {
- copyshrinkdigits(y, n/BI_DIGIT_BITS);
- }
-
- template<int X_DIGITS, int Y_DIGITS> bigint &mul(const bigint<X_DIGITS> &x, const bigint<Y_DIGITS> &y)
- {
- if(!x.len || !y.len) { len = 0; return *this; }
- memset(digits, 0, y.len*sizeof(digit));
- loopi(x.len)
- {
- dbldigit carry = 0;
- loopj(y.len)
- {
- carry += (dbldigit)x.digits[i] * (dbldigit)y.digits[j] + (dbldigit)digits[i+j];
- digits[i+j] = (digit)carry;
- carry >>= BI_DIGIT_BITS;
- }
- digits[i+y.len] = carry;
- }
- len = x.len + y.len;
- shrink();
- return *this;
- }
-
- bigint &rshift(int n)
- {
- assert(len <= BI_DIGITS);
- if(!len || n<=0) return *this;
- if(n >= len*BI_DIGIT_BITS) { len = 0; return *this; }
- int dig = (n-1)/BI_DIGIT_BITS;
- n = ((n-1) % BI_DIGIT_BITS)+1;
- digit carry = digit(digits[dig]>>n);
- for(int i = dig+1; i < len; i++)
- {
- digit tmp = digits[i];
- digits[i-dig-1] = digit((tmp<<(BI_DIGIT_BITS-n)) | carry);
- carry = digit(tmp>>n);
- }
- digits[len-dig-1] = carry;
- len -= dig + (n/BI_DIGIT_BITS);
- shrink();
- return *this;
- }
-
- bigint &lshift(int n)
- {
- if(!len || n<=0) return *this;
- int dig = n/BI_DIGIT_BITS;
- n %= BI_DIGIT_BITS;
- digit carry = 0;
- loopirev(len)
- {
- digit tmp = digits[i];
- digits[i+dig] = digit((tmp<<n) | carry);
- carry = digit(tmp>>(BI_DIGIT_BITS-n));
- }
- len += dig;
- if(carry) digits[len++] = carry;
- if(dig) memset(digits, 0, dig*sizeof(digit));
- return *this;
- }
-
- void zerodigits(int i, int n)
- {
- memset(&digits[i], 0, n*sizeof(digit));
- }
- void zerobits(int i, int n)
- {
- zerodigits(i/BI_DIGIT_BITS, n/BI_DIGIT_BITS);
- }
-
- template<int Y_DIGITS> void copydigits(int to, const bigint<Y_DIGITS> &y, int from, int n)
- {
- int avail = clamp(y.len-from, 0, n);
- memcpy(&digits[to], &y.digits[from], avail*sizeof(digit));
- if(avail < n) memset(&digits[to+avail], 0, (n-avail)*sizeof(digit));
- }
- template<int Y_DIGITS> void copybits(int to, const bigint<Y_DIGITS> &y, int from, int n)
- {
- copydigits(to/BI_DIGIT_BITS, y, from/BI_DIGIT_BITS, n/BI_DIGIT_BITS);
- }
-
- void dupdigits(int to, int from, int n)
- {
- memcpy(&digits[to], &digits[from], n*sizeof(digit));
- }
- void dupbits(int to, int from, int n)
- {
- dupdigits(to/BI_DIGIT_BITS, from/BI_DIGIT_BITS, n/BI_DIGIT_BITS);
- }
-
- template<int Y_DIGITS> bool operator==(const bigint<Y_DIGITS> &y) const
- {
- if(len!=y.len) return false;
- loopirev(len) if(digits[i]!=y.digits[i]) return false;
- return true;
- }
- template<int Y_DIGITS> bool operator!=(const bigint<Y_DIGITS> &y) const { return !(*this==y); }
- template<int Y_DIGITS> bool operator<(const bigint<Y_DIGITS> &y) const
- {
- if(len<y.len) return true;
- if(len>y.len) return false;
- loopirev(len)
- {
- if(digits[i]<y.digits[i]) return true;
- if(digits[i]>y.digits[i]) return false;
- }
- return false;
- }
- template<int Y_DIGITS> bool operator>(const bigint<Y_DIGITS> &y) const { return y<*this; }
- template<int Y_DIGITS> bool operator<=(const bigint<Y_DIGITS> &y) const { return !(y<*this); }
- template<int Y_DIGITS> bool operator>=(const bigint<Y_DIGITS> &y) const { return !(*this<y); }
+ typedef ushort digit;
+ typedef uint dbldigit;
+
+ int len;
+ digit digits[BI_DIGITS];
+
+ bigint() {}
+ bigint(digit n) { if(n) { len = 1; digits[0] = n; } else len = 0; }
+ bigint(const char *s) { parse(s); }
+ template<int Y_DIGITS> bigint(const bigint<Y_DIGITS> &y) { *this = y; }
+
+ static int parsedigits(ushort *digits, int maxlen, const char *s)
+ {
+ int slen = 0;
+ while(isxdigit(s[slen])) slen++;
+ int len = (slen+2*sizeof(ushort)-1)/(2*sizeof(ushort));
+ if(len>maxlen) return 0;
+ memset(digits, 0, len*sizeof(ushort));
+ loopi(slen)
+ {
+ int c = s[slen-i-1];
+ if(isalpha(c)) c = toupper(c) - 'A' + 10;
+ else if(isdigit(c)) c -= '0';
+ else return 0;
+ digits[i/(2*sizeof(ushort))] |= c<<(4*(i%(2*sizeof(ushort))));
+ }
+ return len;
+ }
+
+ void parse(const char *s)
+ {
+ len = parsedigits(digits, BI_DIGITS, s);
+ shrink();
+ }
+
+ void zero() { len = 0; }
+
+ void print(stream *out) const
+ {
+ vector<char> buf;
+ printdigits(buf);
+ out->write(buf.getbuf(), buf.length());
+ }
+
+ void printdigits(vector<char> &buf) const
+ {
+ loopi(len)
+ {
+ digit d = digits[len-i-1];
+ loopj(BI_DIGIT_BITS/4)
+ {
+ uint shift = BI_DIGIT_BITS - (j+1)*4;
+ int val = (d >> shift) & 0xF;
+ if(val < 10) buf.add('0' + val);
+ else buf.add('a' + val - 10);
+ }
+ }
+ }
+
+ template<int Y_DIGITS> bigint &operator=(const bigint<Y_DIGITS> &y)
+ {
+ len = y.len;
+ memcpy(digits, y.digits, len*sizeof(digit));
+ return *this;
+ }
+
+ bool iszero() const { return !len; }
+ bool isone() const { return len==1 && digits[0]==1; }
+
+ int numbits() const
+ {
+ if(!len) return 0;
+ int bits = len*BI_DIGIT_BITS;
+ digit last = digits[len-1], mask = 1<<(BI_DIGIT_BITS-1);
+ while(mask)
+ {
+ if(last&mask) return bits;
+ bits--;
+ mask >>= 1;
+ }
+ return 0;
+ }
+
+ bool hasbit(int n) const { return n/BI_DIGIT_BITS < len && ((digits[n/BI_DIGIT_BITS]>>(n%BI_DIGIT_BITS))&1); }
+
+ bool morebits(int n) const { return len > n/BI_DIGIT_BITS; }
+
+ template<int X_DIGITS, int Y_DIGITS> bigint &add(const bigint<X_DIGITS> &x, const bigint<Y_DIGITS> &y)
+ {
+ dbldigit carry = 0;
+ int maxlen = max(x.len, y.len), i;
+ for(i = 0; i < y.len || carry; i++)
+ {
+ carry += (i < x.len ? (dbldigit)x.digits[i] : 0) + (i < y.len ? (dbldigit)y.digits[i] : 0);
+ digits[i] = (digit)carry;
+ carry >>= BI_DIGIT_BITS;
+ }
+ if(i < x.len && this != &x) memcpy(&digits[i], &x.digits[i], (x.len - i)*sizeof(digit));
+ len = max(i, maxlen);
+ return *this;
+ }
+ template<int Y_DIGITS> bigint &add(const bigint<Y_DIGITS> &y) { return add(*this, y); }
+
+ template<int X_DIGITS, int Y_DIGITS> bigint &sub(const bigint<X_DIGITS> &x, const bigint<Y_DIGITS> &y)
+ {
+ ASSERT(x >= y);
+ dbldigit borrow = 0;
+ int i;
+ for(i = 0; i < y.len || borrow; i++)
+ {
+ borrow = (1<<BI_DIGIT_BITS) + (dbldigit)x.digits[i] - (i<y.len ? (dbldigit)y.digits[i] : 0) - borrow;
+ digits[i] = (digit)borrow;
+ borrow = (borrow>>BI_DIGIT_BITS)^1;
+ }
+ if(i < x.len && this != &x) memcpy(&digits[i], &x.digits[i], (x.len - i)*sizeof(digit));
+ len = x.len;
+ shrink();
+ return *this;
+ }
+ template<int Y_DIGITS> bigint &sub(const bigint<Y_DIGITS> &y) { return sub(*this, y); }
+
+ void shrink() { while(len > 0 && !digits[len-1]) len--; }
+ void shrinkdigits(int n) { len = n; shrink(); }
+ void shrinkbits(int n) { shrinkdigits(n/BI_DIGIT_BITS); }
+
+ template<int Y_DIGITS> void copyshrinkdigits(const bigint<Y_DIGITS> &y, int n)
+ {
+ len = clamp(y.len, 0, n);
+ memcpy(digits, y.digits, len*sizeof(digit));
+ shrink();
+ }
+ template<int Y_DIGITS> void copyshrinkbits(const bigint<Y_DIGITS> &y, int n)
+ {
+ copyshrinkdigits(y, n/BI_DIGIT_BITS);
+ }
+
+ template<int X_DIGITS, int Y_DIGITS> bigint &mul(const bigint<X_DIGITS> &x, const bigint<Y_DIGITS> &y)
+ {
+ if(!x.len || !y.len) { len = 0; return *this; }
+ memset(digits, 0, y.len*sizeof(digit));
+ loopi(x.len)
+ {
+ dbldigit carry = 0;
+ loopj(y.len)
+ {
+ carry += (dbldigit)x.digits[i] * (dbldigit)y.digits[j] + (dbldigit)digits[i+j];
+ digits[i+j] = (digit)carry;
+ carry >>= BI_DIGIT_BITS;
+ }
+ digits[i+y.len] = carry;
+ }
+ len = x.len + y.len;
+ shrink();
+ return *this;
+ }
+
+ bigint &rshift(int n)
+ {
+ assert(len <= BI_DIGITS);
+ if(!len || n<=0) return *this;
+ if(n >= len*BI_DIGIT_BITS) { len = 0; return *this; }
+ int dig = (n-1)/BI_DIGIT_BITS;
+ n = ((n-1) % BI_DIGIT_BITS)+1;
+ digit carry = digit(digits[dig]>>n);
+ for(int i = dig+1; i < len; i++)
+ {
+ digit tmp = digits[i];
+ digits[i-dig-1] = digit((tmp<<(BI_DIGIT_BITS-n)) | carry);
+ carry = digit(tmp>>n);
+ }
+ digits[len-dig-1] = carry;
+ len -= dig + (n/BI_DIGIT_BITS);
+ shrink();
+ return *this;
+ }
+
+ bigint &lshift(int n)
+ {
+ if(!len || n<=0) return *this;
+ int dig = n/BI_DIGIT_BITS;
+ n %= BI_DIGIT_BITS;
+ digit carry = 0;
+ loopirev(len)
+ {
+ digit tmp = digits[i];
+ digits[i+dig] = digit((tmp<<n) | carry);
+ carry = digit(tmp>>(BI_DIGIT_BITS-n));
+ }
+ len += dig;
+ if(carry) digits[len++] = carry;
+ if(dig) memset(digits, 0, dig*sizeof(digit));
+ return *this;
+ }
+
+ void zerodigits(int i, int n)
+ {
+ memset(&digits[i], 0, n*sizeof(digit));
+ }
+ void zerobits(int i, int n)
+ {
+ zerodigits(i/BI_DIGIT_BITS, n/BI_DIGIT_BITS);
+ }
+
+ template<int Y_DIGITS> void copydigits(int to, const bigint<Y_DIGITS> &y, int from, int n)
+ {
+ int avail = clamp(y.len-from, 0, n);
+ memcpy(&digits[to], &y.digits[from], avail*sizeof(digit));
+ if(avail < n) memset(&digits[to+avail], 0, (n-avail)*sizeof(digit));
+ }
+ template<int Y_DIGITS> void copybits(int to, const bigint<Y_DIGITS> &y, int from, int n)
+ {
+ copydigits(to/BI_DIGIT_BITS, y, from/BI_DIGIT_BITS, n/BI_DIGIT_BITS);
+ }
+
+ void dupdigits(int to, int from, int n)
+ {
+ memcpy(&digits[to], &digits[from], n*sizeof(digit));
+ }
+ void dupbits(int to, int from, int n)
+ {
+ dupdigits(to/BI_DIGIT_BITS, from/BI_DIGIT_BITS, n/BI_DIGIT_BITS);
+ }
+
+ template<int Y_DIGITS> bool operator==(const bigint<Y_DIGITS> &y) const
+ {
+ if(len!=y.len) return false;
+ loopirev(len) if(digits[i]!=y.digits[i]) return false;
+ return true;
+ }
+ template<int Y_DIGITS> bool operator!=(const bigint<Y_DIGITS> &y) const { return !(*this==y); }
+ template<int Y_DIGITS> bool operator<(const bigint<Y_DIGITS> &y) const
+ {
+ if(len<y.len) return true;
+ if(len>y.len) return false;
+ loopirev(len)
+ {
+ if(digits[i]<y.digits[i]) return true;
+ if(digits[i]>y.digits[i]) return false;
+ }
+ return false;
+ }
+ template<int Y_DIGITS> bool operator>(const bigint<Y_DIGITS> &y) const { return y<*this; }
+ template<int Y_DIGITS> bool operator<=(const bigint<Y_DIGITS> &y) const { return !(y<*this); }
+ template<int Y_DIGITS> bool operator>=(const bigint<Y_DIGITS> &y) const { return !(*this<y); }
};
-#define GF_BITS 192
-#define GF_DIGITS ((GF_BITS+BI_DIGIT_BITS-1)/BI_DIGIT_BITS)
+#define GF_BITS 192
+#define GF_DIGITS ((GF_BITS+BI_DIGIT_BITS-1)/BI_DIGIT_BITS)
typedef bigint<GF_DIGITS+1> gfint;
@@ -420,380 +420,380 @@ typedef bigint<GF_DIGITS+1> gfint;
*/
struct gfield : gfint
{
- static const gfield P;
-
- gfield() {}
- gfield(digit n) : gfint(n) {}
- gfield(const char *s) : gfint(s) {}
-
- template<int Y_DIGITS> gfield(const bigint<Y_DIGITS> &y) : gfint(y) {}
-
- template<int Y_DIGITS> gfield &operator=(const bigint<Y_DIGITS> &y)
- {
- gfint::operator=(y);
- return *this;
- }
-
- template<int X_DIGITS, int Y_DIGITS> gfield &add(const bigint<X_DIGITS> &x, const bigint<Y_DIGITS> &y)
- {
- gfint::add(x, y);
- if(*this >= P) gfint::sub(*this, P);
- return *this;
- }
- template<int Y_DIGITS> gfield &add(const bigint<Y_DIGITS> &y) { return add(*this, y); }
-
- template<int X_DIGITS> gfield &mul2(const bigint<X_DIGITS> &x) { return add(x, x); }
- gfield &mul2() { return mul2(*this); }
-
- gfield &div2()
- {
- if(hasbit(0)) gfint::add(*this, P);
- rshift(1);
- return *this;
- }
-
- template<int X_DIGITS, int Y_DIGITS> gfield &sub(const bigint<X_DIGITS> &x, const bigint<Y_DIGITS> &y)
- {
- if(x < y)
- {
- gfint tmp; /* necessary if this==&y, using this instead would clobber y */
- tmp.add(x, P);
- gfint::sub(tmp, y);
- }
- else gfint::sub(x, y);
- return *this;
- }
- template<int Y_DIGITS> gfield &sub(const bigint<Y_DIGITS> &y) { return sub(*this, y); }
-
- template<int X_DIGITS> gfield &neg(const bigint<X_DIGITS> &x)
- {
- gfint::sub(P, x);
- return *this;
- }
- gfield &neg() { return neg(*this); }
-
- template<int X_DIGITS> gfield &square(const bigint<X_DIGITS> &x) { return mul(x, x); }
- gfield &square() { return square(*this); }
-
- template<int X_DIGITS, int Y_DIGITS> gfield &mul(const bigint<X_DIGITS> &x, const bigint<Y_DIGITS> &y)
- {
- bigint<X_DIGITS+Y_DIGITS> result;
- result.mul(x, y);
- reduce(result);
- return *this;
- }
- template<int Y_DIGITS> gfield &mul(const bigint<Y_DIGITS> &y) { return mul(*this, y); }
-
- template<int RESULT_DIGITS> void reduce(const bigint<RESULT_DIGITS> &result)
- {
+ static const gfield P;
+
+ gfield() {}
+ gfield(digit n) : gfint(n) {}
+ gfield(const char *s) : gfint(s) {}
+
+ template<int Y_DIGITS> gfield(const bigint<Y_DIGITS> &y) : gfint(y) {}
+
+ template<int Y_DIGITS> gfield &operator=(const bigint<Y_DIGITS> &y)
+ {
+ gfint::operator=(y);
+ return *this;
+ }
+
+ template<int X_DIGITS, int Y_DIGITS> gfield &add(const bigint<X_DIGITS> &x, const bigint<Y_DIGITS> &y)
+ {
+ gfint::add(x, y);
+ if(*this >= P) gfint::sub(*this, P);
+ return *this;
+ }
+ template<int Y_DIGITS> gfield &add(const bigint<Y_DIGITS> &y) { return add(*this, y); }
+
+ template<int X_DIGITS> gfield &mul2(const bigint<X_DIGITS> &x) { return add(x, x); }
+ gfield &mul2() { return mul2(*this); }
+
+ gfield &div2()
+ {
+ if(hasbit(0)) gfint::add(*this, P);
+ rshift(1);
+ return *this;
+ }
+
+ template<int X_DIGITS, int Y_DIGITS> gfield &sub(const bigint<X_DIGITS> &x, const bigint<Y_DIGITS> &y)
+ {
+ if(x < y)
+ {
+ gfint tmp; /* necessary if this==&y, using this instead would clobber y */
+ tmp.add(x, P);
+ gfint::sub(tmp, y);
+ }
+ else gfint::sub(x, y);
+ return *this;
+ }
+ template<int Y_DIGITS> gfield &sub(const bigint<Y_DIGITS> &y) { return sub(*this, y); }
+
+ template<int X_DIGITS> gfield &neg(const bigint<X_DIGITS> &x)
+ {
+ gfint::sub(P, x);
+ return *this;
+ }
+ gfield &neg() { return neg(*this); }
+
+ template<int X_DIGITS> gfield &square(const bigint<X_DIGITS> &x) { return mul(x, x); }
+ gfield &square() { return square(*this); }
+
+ template<int X_DIGITS, int Y_DIGITS> gfield &mul(const bigint<X_DIGITS> &x, const bigint<Y_DIGITS> &y)
+ {
+ bigint<X_DIGITS+Y_DIGITS> result;
+ result.mul(x, y);
+ reduce(result);
+ return *this;
+ }
+ template<int Y_DIGITS> gfield &mul(const bigint<Y_DIGITS> &y) { return mul(*this, y); }
+
+ template<int RESULT_DIGITS> void reduce(const bigint<RESULT_DIGITS> &result)
+ {
#if GF_BITS==192
- // B = T + S1 + S2 + S3 mod p
- copyshrinkdigits(result, GF_DIGITS); // T
-
- if(result.morebits(192))
- {
- gfield s;
- s.copybits(0, result, 192, 64);
- s.dupbits(64, 0, 64);
- s.shrinkbits(128);
- add(s); // S1
-
- if(result.morebits(256))
- {
- s.zerobits(0, 64);
- s.copybits(64, result, 256, 64);
- s.dupbits(128, 64, 64);
- s.shrinkdigits(GF_DIGITS);
- add(s); // S2
-
- if(result.morebits(320))
- {
- s.copybits(0, result, 320, 64);
- s.dupbits(64, 0, 64);
- s.dupbits(128, 0, 64);
- s.shrinkdigits(GF_DIGITS);
- add(s); // S3
- }
- }
- }
- else if(*this >= P) gfint::sub(*this, P);
+ // B = T + S1 + S2 + S3 mod p
+ copyshrinkdigits(result, GF_DIGITS); // T
+
+ if(result.morebits(192))
+ {
+ gfield s;
+ s.copybits(0, result, 192, 64);
+ s.dupbits(64, 0, 64);
+ s.shrinkbits(128);
+ add(s); // S1
+
+ if(result.morebits(256))
+ {
+ s.zerobits(0, 64);
+ s.copybits(64, result, 256, 64);
+ s.dupbits(128, 64, 64);
+ s.shrinkdigits(GF_DIGITS);
+ add(s); // S2
+
+ if(result.morebits(320))
+ {
+ s.copybits(0, result, 320, 64);
+ s.dupbits(64, 0, 64);
+ s.dupbits(128, 0, 64);
+ s.shrinkdigits(GF_DIGITS);
+ add(s); // S3
+ }
+ }
+ }
+ else if(*this >= P) gfint::sub(*this, P);
#elif GF_BITS==256
- // B = T + 2*S1 + 2*S2 + S3 + S4 - D1 - D2 - D3 - D4 mod p
- copyshrinkdigits(result, GF_DIGITS); // T
-
- if(result.morebits(256))
- {
- gfield s;
- if(result.morebits(352))
- {
- s.zerobits(0, 96);
- s.copybits(96, result, 352, 160);
- s.shrinkdigits(GF_DIGITS);
- add(s); add(s); // S1
-
- if(result.morebits(384))
- {
- //s.zerobits(0, 96);
- s.copybits(96, result, 384, 128);
- s.shrinkbits(224);
- add(s); add(s); // S2
- }
- }
-
- s.copybits(0, result, 256, 96);
- s.zerobits(96, 96);
- s.copybits(192, result, 448, 64);
- s.shrinkdigits(GF_DIGITS);
- add(s); // S3
-
- s.copybits(0, result, 288, 96);
- s.copybits(96, result, 416, 96);
- s.dupbits(192, 96, 32);
- s.copybits(224, result, 256, 32);
- s.shrinkdigits(GF_DIGITS);
- add(s); // S4
-
- s.copybits(0, result, 352, 96);
- s.zerobits(96, 96);
- s.copybits(192, result, 256, 32);
- s.copybits(224, result, 320, 32);
- s.shrinkdigits(GF_DIGITS);
- sub(s); // D1
-
- s.copybits(0, result, 384, 128);
- //s.zerobits(128, 64);
- s.copybits(192, result, 288, 32);
- s.copybits(224, result, 352, 32);
- s.shrinkdigits(GF_DIGITS);
- sub(s); // D2
-
- s.copybits(0, result, 416, 96);
- s.copybits(96, result, 256, 96);
- s.zerobits(192, 32);
- s.copybits(224, result, 384, 32);
- s.shrinkdigits(GF_DIGITS);
- sub(s); // D3
-
- s.copybits(0, result, 448, 64);
- s.zerobits(64, 32);
- s.copybits(96, result, 288, 96);
- //s.zerobits(192, 32);
- s.copybits(224, result, 416, 32);
- s.shrinkdigits(GF_DIGITS);
- sub(s); // D4
- }
- else if(*this >= P) gfint::sub(*this, P);
+ // B = T + 2*S1 + 2*S2 + S3 + S4 - D1 - D2 - D3 - D4 mod p
+ copyshrinkdigits(result, GF_DIGITS); // T
+
+ if(result.morebits(256))
+ {
+ gfield s;
+ if(result.morebits(352))
+ {
+ s.zerobits(0, 96);
+ s.copybits(96, result, 352, 160);
+ s.shrinkdigits(GF_DIGITS);
+ add(s); add(s); // S1
+
+ if(result.morebits(384))
+ {
+ //s.zerobits(0, 96);
+ s.copybits(96, result, 384, 128);
+ s.shrinkbits(224);
+ add(s); add(s); // S2
+ }
+ }
+
+ s.copybits(0, result, 256, 96);
+ s.zerobits(96, 96);
+ s.copybits(192, result, 448, 64);
+ s.shrinkdigits(GF_DIGITS);
+ add(s); // S3
+
+ s.copybits(0, result, 288, 96);
+ s.copybits(96, result, 416, 96);
+ s.dupbits(192, 96, 32);
+ s.copybits(224, result, 256, 32);
+ s.shrinkdigits(GF_DIGITS);
+ add(s); // S4
+
+ s.copybits(0, result, 352, 96);
+ s.zerobits(96, 96);
+ s.copybits(192, result, 256, 32);
+ s.copybits(224, result, 320, 32);
+ s.shrinkdigits(GF_DIGITS);
+ sub(s); // D1
+
+ s.copybits(0, result, 384, 128);
+ //s.zerobits(128, 64);
+ s.copybits(192, result, 288, 32);
+ s.copybits(224, result, 352, 32);
+ s.shrinkdigits(GF_DIGITS);
+ sub(s); // D2
+
+ s.copybits(0, result, 416, 96);
+ s.copybits(96, result, 256, 96);
+ s.zerobits(192, 32);
+ s.copybits(224, result, 384, 32);
+ s.shrinkdigits(GF_DIGITS);
+ sub(s); // D3
+
+ s.copybits(0, result, 448, 64);
+ s.zerobits(64, 32);
+ s.copybits(96, result, 288, 96);
+ //s.zerobits(192, 32);
+ s.copybits(224, result, 416, 32);
+ s.shrinkdigits(GF_DIGITS);
+ sub(s); // D4
+ }
+ else if(*this >= P) gfint::sub(*this, P);
#else
#error Unsupported GF
#endif
- }
-
- template<int X_DIGITS, int Y_DIGITS> gfield &pow(const bigint<X_DIGITS> &x, const bigint<Y_DIGITS> &y)
- {
- gfield a(x);
- if(y.hasbit(0)) *this = a;
- else
- {
- len = 1;
- digits[0] = 1;
- if(!y.len) return *this;
- }
- for(int i = 1, j = y.numbits(); i < j; i++)
- {
- a.square();
- if(y.hasbit(i)) mul(a);
- }
- return *this;
- }
- template<int Y_DIGITS> gfield &pow(const bigint<Y_DIGITS> &y) { return pow(*this, y); }
-
- bool invert(const gfield &x)
- {
- if(!x.len) return false;
- gfint u(x), v(P), A((gfint::digit)1), C((gfint::digit)0);
- while(!u.iszero())
- {
- int ushift = 0, ashift = 0;
- while(!u.hasbit(ushift))
- {
- ushift++;
- if(A.hasbit(ashift))
- {
- if(ashift) { A.rshift(ashift); ashift = 0; }
- A.add(P);
- }
- ashift++;
- }
- if(ushift) u.rshift(ushift);
- if(ashift) A.rshift(ashift);
- int vshift = 0, cshift = 0;
- while(!v.hasbit(vshift))
- {
- vshift++;
- if(C.hasbit(cshift))
- {
- if(cshift) { C.rshift(cshift); cshift = 0; }
- C.add(P);
- }
- cshift++;
- }
- if(vshift) v.rshift(vshift);
- if(cshift) C.rshift(cshift);
- if(u >= v)
- {
- u.sub(v);
- if(A < C) A.add(P);
- A.sub(C);
- }
- else
- {
- v.sub(v, u);
- if(C < A) C.add(P);
- C.sub(A);
- }
- }
- if(C >= P) gfint::sub(C, P);
- else { len = C.len; memcpy(digits, C.digits, len*sizeof(digit)); }
- ASSERT(*this < P);
- return true;
- }
- void invert() { invert(*this); }
-
- template<int X_DIGITS> static int legendre(const bigint<X_DIGITS> &x)
- {
- static const gfint Psub1div2(gfint(P).sub(bigint<1>(1)).rshift(1));
- gfield L;
- L.pow(x, Psub1div2);
- if(!L.len) return 0;
- if(L.len==1) return 1;
- return -1;
- }
- int legendre() const { return legendre(*this); }
-
- bool sqrt(const gfield &x)
- {
- if(!x.len) { len = 0; return true; }
+ }
+
+ template<int X_DIGITS, int Y_DIGITS> gfield &pow(const bigint<X_DIGITS> &x, const bigint<Y_DIGITS> &y)
+ {
+ gfield a(x);
+ if(y.hasbit(0)) *this = a;
+ else
+ {
+ len = 1;
+ digits[0] = 1;
+ if(!y.len) return *this;
+ }
+ for(int i = 1, j = y.numbits(); i < j; i++)
+ {
+ a.square();
+ if(y.hasbit(i)) mul(a);
+ }
+ return *this;
+ }
+ template<int Y_DIGITS> gfield &pow(const bigint<Y_DIGITS> &y) { return pow(*this, y); }
+
+ bool invert(const gfield &x)
+ {
+ if(!x.len) return false;
+ gfint u(x), v(P), A((gfint::digit)1), C((gfint::digit)0);
+ while(!u.iszero())
+ {
+ int ushift = 0, ashift = 0;
+ while(!u.hasbit(ushift))
+ {
+ ushift++;
+ if(A.hasbit(ashift))
+ {
+ if(ashift) { A.rshift(ashift); ashift = 0; }
+ A.add(P);
+ }
+ ashift++;
+ }
+ if(ushift) u.rshift(ushift);
+ if(ashift) A.rshift(ashift);
+ int vshift = 0, cshift = 0;
+ while(!v.hasbit(vshift))
+ {
+ vshift++;
+ if(C.hasbit(cshift))
+ {
+ if(cshift) { C.rshift(cshift); cshift = 0; }
+ C.add(P);
+ }
+ cshift++;
+ }
+ if(vshift) v.rshift(vshift);
+ if(cshift) C.rshift(cshift);
+ if(u >= v)
+ {
+ u.sub(v);
+ if(A < C) A.add(P);
+ A.sub(C);
+ }
+ else
+ {
+ v.sub(v, u);
+ if(C < A) C.add(P);
+ C.sub(A);
+ }
+ }
+ if(C >= P) gfint::sub(C, P);
+ else { len = C.len; memcpy(digits, C.digits, len*sizeof(digit)); }
+ ASSERT(*this < P);
+ return true;
+ }
+ void invert() { invert(*this); }
+
+ template<int X_DIGITS> static int legendre(const bigint<X_DIGITS> &x)
+ {
+ static const gfint Psub1div2(gfint(P).sub(bigint<1>(1)).rshift(1));
+ gfield L;
+ L.pow(x, Psub1div2);
+ if(!L.len) return 0;
+ if(L.len==1) return 1;
+ return -1;
+ }
+ int legendre() const { return legendre(*this); }
+
+ bool sqrt(const gfield &x)
+ {
+ if(!x.len) { len = 0; return true; }
#if GF_BITS==224
#error Unsupported GF
#else
- ASSERT((P.digits[0]%4)==3);
- static const gfint Padd1div4(gfint(P).add(bigint<1>(1)).rshift(2));
- switch(legendre(x))
- {
- case 0: len = 0; return true;
- case -1: return false;
- default: pow(x, Padd1div4); return true;
- }
+ ASSERT((P.digits[0]%4)==3);
+ static const gfint Padd1div4(gfint(P).add(bigint<1>(1)).rshift(2));
+ switch(legendre(x))
+ {
+ case 0: len = 0; return true;
+ case -1: return false;
+ default: pow(x, Padd1div4); return true;
+ }
#endif
- }
- bool sqrt() { return sqrt(*this); }
+ }
+ bool sqrt() { return sqrt(*this); }
};
struct ecjacobian
{
- static const gfield B;
- static const ecjacobian base;
- static const ecjacobian origin;
-
- gfield x, y, z;
-
- ecjacobian() {}
- ecjacobian(const gfield &x, const gfield &y) : x(x), y(y), z(bigint<1>(1)) {}
- ecjacobian(const gfield &x, const gfield &y, const gfield &z) : x(x), y(y), z(z) {}
-
- void mul2()
- {
- if(z.iszero()) return;
- else if(y.iszero()) { *this = origin; return; }
- gfield a, b, c, d;
- d.sub(x, c.square(z));
- d.mul(c.add(x));
- c.mul2(d).add(d);
- z.mul(y).add(z);
- a.square(y);
- b.mul2(a);
- d.mul2(x).mul(b);
- x.square(c).sub(d).sub(d);
- a.square(b).add(a);
- y.sub(d, x).mul(c).sub(a);
- }
-
- void add(const ecjacobian &q)
- {
- if(q.z.iszero()) return;
- else if(z.iszero()) { *this = q; return; }
- gfield a, b, c, d, e, f;
- a.square(z);
- b.mul(q.y, a).mul(z);
- a.mul(q.x);
- if(q.z.isone())
- {
- c.add(x, a);
- d.add(y, b);
- a.sub(x, a);
- b.sub(y, b);
- }
- else
- {
- f.mul(y, e.square(q.z)).mul(q.z);
- e.mul(x);
- c.add(e, a);
- d.add(f, b);
- a.sub(e, a);
- b.sub(f, b);
- }
- if(a.iszero()) { if(b.iszero()) mul2(); else *this = origin; return; }
- if(!q.z.isone()) z.mul(q.z);
- z.mul(a);
- x.square(b).sub(f.mul(c, e.square(a)));
- y.sub(f, x).sub(x).mul(b).sub(e.mul(a).mul(d)).div2();
- }
-
- template<int Q_DIGITS> void mul(const ecjacobian &p, const bigint<Q_DIGITS> &q)
- {
- *this = origin;
- loopirev(q.numbits())
- {
- mul2();
- if(q.hasbit(i)) add(p);
- }
- }
- template<int Q_DIGITS> void mul(const bigint<Q_DIGITS> &q) { ecjacobian tmp(*this); mul(tmp, q); }
-
- void normalize()
- {
- if(z.iszero() || z.isone()) return;
- gfield tmp;
- z.invert();
- tmp.square(z);
- x.mul(tmp);
- y.mul(tmp).mul(z);
- z = bigint<1>(1);
- }
-
- bool calcy(bool ybit)
- {
- gfield y2, tmp;
- y2.square(x).mul(x).sub(tmp.add(x, x).add(x)).add(B);
- if(!y.sqrt(y2)) { y.zero(); return false; }
- if(y.hasbit(0) != ybit) y.neg();
- return true;
- }
-
- void print(vector<char> &buf)
- {
- normalize();
- buf.add(y.hasbit(0) ? '-' : '+');
- x.printdigits(buf);
- }
-
- void parse(const char *s)
- {
- bool ybit = *s++ == '-';
- x.parse(s);
- calcy(ybit);
- z = bigint<1>(1);
- }
+ static const gfield B;
+ static const ecjacobian base;
+ static const ecjacobian origin;
+
+ gfield x, y, z;
+
+ ecjacobian() {}
+ ecjacobian(const gfield &x, const gfield &y) : x(x), y(y), z(bigint<1>(1)) {}
+ ecjacobian(const gfield &x, const gfield &y, const gfield &z) : x(x), y(y), z(z) {}
+
+ void mul2()
+ {
+ if(z.iszero()) return;
+ else if(y.iszero()) { *this = origin; return; }
+ gfield a, b, c, d;
+ d.sub(x, c.square(z));
+ d.mul(c.add(x));
+ c.mul2(d).add(d);
+ z.mul(y).add(z);
+ a.square(y);
+ b.mul2(a);
+ d.mul2(x).mul(b);
+ x.square(c).sub(d).sub(d);
+ a.square(b).add(a);
+ y.sub(d, x).mul(c).sub(a);
+ }
+
+ void add(const ecjacobian &q)
+ {
+ if(q.z.iszero()) return;
+ else if(z.iszero()) { *this = q; return; }
+ gfield a, b, c, d, e, f;
+ a.square(z);
+ b.mul(q.y, a).mul(z);
+ a.mul(q.x);
+ if(q.z.isone())
+ {
+ c.add(x, a);
+ d.add(y, b);
+ a.sub(x, a);
+ b.sub(y, b);
+ }
+ else
+ {
+ f.mul(y, e.square(q.z)).mul(q.z);
+ e.mul(x);
+ c.add(e, a);
+ d.add(f, b);
+ a.sub(e, a);
+ b.sub(f, b);
+ }
+ if(a.iszero()) { if(b.iszero()) mul2(); else *this = origin; return; }
+ if(!q.z.isone()) z.mul(q.z);
+ z.mul(a);
+ x.square(b).sub(f.mul(c, e.square(a)));
+ y.sub(f, x).sub(x).mul(b).sub(e.mul(a).mul(d)).div2();
+ }
+
+ template<int Q_DIGITS> void mul(const ecjacobian &p, const bigint<Q_DIGITS> &q)
+ {
+ *this = origin;
+ loopirev(q.numbits())
+ {
+ mul2();
+ if(q.hasbit(i)) add(p);
+ }
+ }
+ template<int Q_DIGITS> void mul(const bigint<Q_DIGITS> &q) { ecjacobian tmp(*this); mul(tmp, q); }
+
+ void normalize()
+ {
+ if(z.iszero() || z.isone()) return;
+ gfield tmp;
+ z.invert();
+ tmp.square(z);
+ x.mul(tmp);
+ y.mul(tmp).mul(z);
+ z = bigint<1>(1);
+ }
+
+ bool calcy(bool ybit)
+ {
+ gfield y2, tmp;
+ y2.square(x).mul(x).sub(tmp.add(x, x).add(x)).add(B);
+ if(!y.sqrt(y2)) { y.zero(); return false; }
+ if(y.hasbit(0) != ybit) y.neg();
+ return true;
+ }
+
+ void print(vector<char> &buf)
+ {
+ normalize();
+ buf.add(y.hasbit(0) ? '-' : '+');
+ x.printdigits(buf);
+ }
+
+ void parse(const char *s)
+ {
+ bool ybit = *s++ == '-';
+ x.parse(s);
+ calcy(ybit);
+ z = bigint<1>(1);
+ }
};
const ecjacobian ecjacobian::origin(gfield((gfield::digit)1), gfield((gfield::digit)1), gfield((gfield::digit)0));
@@ -802,36 +802,36 @@ const ecjacobian ecjacobian::origin(gfield((gfield::digit)1), gfield((gfield::di
const gfield gfield::P("fffffffffffffffffffffffffffffffeffffffffffffffff");
const gfield ecjacobian::B("64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1");
const ecjacobian ecjacobian::base(
- gfield("188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012"),
- gfield("07192b95ffc8da78631011ed6b24cdd573f977a11e794811")
+ gfield("188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012"),
+ gfield("07192b95ffc8da78631011ed6b24cdd573f977a11e794811")
);
#elif GF_BITS==224
const gfield gfield::P("ffffffffffffffffffffffffffffffff000000000000000000000001");
const gfield ecjacobian::B("b4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4");
const ecjacobian ecjacobian::base(
- gfield("b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21"),
- gfield("bd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34")
+ gfield("b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21"),
+ gfield("bd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34")
);
#elif GF_BITS==256
const gfield gfield::P("ffffffff00000001000000000000000000000000ffffffffffffffffffffffff");
const gfield ecjacobian::B("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b");
const ecjacobian ecjacobian::base(
- gfield("6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296"),
- gfield("4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5")
+ gfield("6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296"),
+ gfield("4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5")
);
#elif GF_BITS==384
const gfield gfield::P("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff");
const gfield ecjacobian::B("b3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef");
const ecjacobian ecjacobian::base(
- gfield("aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7"),
- gfield("3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f")
+ gfield("aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7"),
+ gfield("3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f")
);
#elif GF_BITS==521
const gfield gfield::P("1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
const gfield ecjacobian::B("051953eb968e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00");
const ecjacobian ecjacobian::base(
- gfield("c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66"),
- gfield("11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650")
+ gfield("c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66"),
+ gfield("11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650")
);
#else
#error Unsupported GF
@@ -839,106 +839,106 @@ const ecjacobian ecjacobian::base(
void calcpubkey(gfint privkey, vector<char> &pubstr)
{
- ecjacobian c(ecjacobian::base);
- c.mul(privkey);
- c.normalize();
- c.print(pubstr);
- pubstr.add('\0');
+ ecjacobian c(ecjacobian::base);
+ c.mul(privkey);
+ c.normalize();
+ c.print(pubstr);
+ pubstr.add('\0');
}
bool calcpubkey(const char *privstr, vector<char> &pubstr)
{
- if(!privstr[0]) return false;
- gfint privkey;
- privkey.parse(privstr);
- calcpubkey(privkey, pubstr);
- return true;
+ if(!privstr[0]) return false;
+ gfint privkey;
+ privkey.parse(privstr);
+ calcpubkey(privkey, pubstr);
+ return true;
}
void genprivkey(const char *seed, vector<char> &privstr, vector<char> &pubstr)
{
- tiger::hashval hash;
- tiger::hash((const uchar *)seed, (int)strlen(seed), hash);
- bigint<8*sizeof(hash.bytes)/BI_DIGIT_BITS> privkey;
- memcpy(privkey.digits, hash.bytes, sizeof(hash.bytes));
- privkey.len = 8*sizeof(hash.bytes)/BI_DIGIT_BITS;
- privkey.shrink();
- privkey.printdigits(privstr);
- privstr.add('\0');
-
- calcpubkey(privkey, pubstr);
+ tiger::hashval hash;
+ tiger::hash((const uchar *)seed, (int)strlen(seed), hash);
+ bigint<8*sizeof(hash.bytes)/BI_DIGIT_BITS> privkey;
+ memcpy(privkey.digits, hash.bytes, sizeof(hash.bytes));
+ privkey.len = 8*sizeof(hash.bytes)/BI_DIGIT_BITS;
+ privkey.shrink();
+ privkey.printdigits(privstr);
+ privstr.add('\0');
+
+ calcpubkey(privkey, pubstr);
}
bool hashstring(const char *str, char *result, int maxlen)
{
- tiger::hashval hv;
- if(maxlen < 2*(int)sizeof(hv.bytes) + 1) return false;
- tiger::hash((uchar *)str, strlen(str), hv);
- loopi(sizeof(hv.bytes))
- {
- uchar c = hv.bytes[i];
- *result++ = "0123456789abcdef"[c&0xF];
- *result++ = "0123456789abcdef"[c>>4];
- }
- *result = '\0';
- return true;
+ tiger::hashval hv;
+ if(maxlen < 2*(int)sizeof(hv.bytes) + 1) return false;
+ tiger::hash((uchar *)str, strlen(str), hv);
+ loopi(sizeof(hv.bytes))
+ {
+ uchar c = hv.bytes[i];
+ *result++ = "0123456789abcdef"[c&0xF];
+ *result++ = "0123456789abcdef"[c>>4];
+ }
+ *result = '\0';
+ return true;
}
void answerchallenge(const char *privstr, const char *challenge, vector<char> &answerstr)
{
- gfint privkey;
- privkey.parse(privstr);
- ecjacobian answer;
- answer.parse(challenge);
- answer.mul(privkey);
- answer.normalize();
- answer.x.printdigits(answerstr);
- answerstr.add('\0');
+ gfint privkey;
+ privkey.parse(privstr);
+ ecjacobian answer;
+ answer.parse(challenge);
+ answer.mul(privkey);
+ answer.normalize();
+ answer.x.printdigits(answerstr);
+ answerstr.add('\0');
}
void *parsepubkey(const char *pubstr)
{
- ecjacobian *pubkey = new ecjacobian;
- pubkey->parse(pubstr);
- return pubkey;
+ ecjacobian *pubkey = new ecjacobian;
+ pubkey->parse(pubstr);
+ return pubkey;
}
void freepubkey(void *pubkey)
{
- delete (ecjacobian *)pubkey;
+ delete (ecjacobian *)pubkey;
}
void *genchallenge(void *pubkey, const void *seed, int seedlen, vector<char> &challengestr)
{
- tiger::hashval hash;
- tiger::hash((const uchar *)seed, seedlen, hash);
- gfint challenge;
- memcpy(challenge.digits, hash.bytes, sizeof(hash.bytes));
- challenge.len = 8*sizeof(hash.bytes)/BI_DIGIT_BITS;
- challenge.shrink();
+ tiger::hashval hash;
+ tiger::hash((const uchar *)seed, seedlen, hash);
+ gfint challenge;
+ memcpy(challenge.digits, hash.bytes, sizeof(hash.bytes));
+ challenge.len = 8*sizeof(hash.bytes)/BI_DIGIT_BITS;
+ challenge.shrink();
- ecjacobian answer(*(ecjacobian *)pubkey);
- answer.mul(challenge);
- answer.normalize();
+ ecjacobian answer(*(ecjacobian *)pubkey);
+ answer.mul(challenge);
+ answer.normalize();
- ecjacobian secret(ecjacobian::base);
- secret.mul(challenge);
- secret.normalize();
+ ecjacobian secret(ecjacobian::base);
+ secret.mul(challenge);
+ secret.normalize();
- secret.print(challengestr);
- challengestr.add('\0');
+ secret.print(challengestr);
+ challengestr.add('\0');
- return new gfield(answer.x);
+ return new gfield(answer.x);
}
void freechallenge(void *answer)
{
- delete (gfint *)answer;
+ delete (gfint *)answer;
}
bool checkchallenge(const char *answerstr, void *correct)
{
- gfint answer(answerstr);
- return answer == *(gfint *)correct;
+ gfint answer(answerstr);
+ return answer == *(gfint *)correct;
}
diff --git a/src/shared/cube.h b/src/shared/cube.h
index ffb1d1b..d804511 100644
--- a/src/shared/cube.h
+++ b/src/shared/cube.h
@@ -3,9 +3,6 @@
#define _FILE_OFFSET_BITS 64
-#ifdef WIN32
-#define _USE_MATH_DEFINES
-#endif
#include <math.h>
#include <string.h>
@@ -17,34 +14,9 @@
#include <assert.h>
#include <time.h>
-#ifdef WIN32
- #define WIN32_LEAN_AND_MEAN
- #ifdef _WIN32_WINNT
- #undef _WIN32_WINNT
- #endif
- #define _WIN32_WINNT 0x0500
- #include "windows.h"
- #ifndef _WINDOWS
- #define _WINDOWS
- #endif
- #ifndef __GNUC__
- #include <eh.h>
- #include <dbghelp.h>
- #include <intrin.h>
- #endif
- #define ZLIB_DLL
-#endif
-
#ifndef STANDALONE
- #ifdef __APPLE__
- #include "SDL.h"
- #define GL_GLEXT_LEGACY
- #define __glext_h_
- #include <OpenGL/gl.h>
- #else
- #include <SDL.h>
- #include <SDL_opengl.h>
- #endif
+ #include <SDL.h>
+ #include <SDL_opengl.h>
#endif
#include <enet/enet.h>
diff --git a/src/shared/cube2font.c b/src/shared/cube2font.c
index 94e407d..75ea8ff 100644
--- a/src/shared/cube2font.c
+++ b/src/shared/cube2font.c
@@ -18,180 +18,180 @@ int imax(int a, int b) { return a > b ? a : b; }
void fatal(const char *fmt, ...)
{
- va_list v;
- va_start(v, fmt);
- vfprintf(stderr, fmt, v);
- va_end(v);
- fputc('\n', stderr);
+ va_list v;
+ va_start(v, fmt);
+ vfprintf(stderr, fmt, v);
+ va_end(v);
+ fputc('\n', stderr);
- exit(EXIT_FAILURE);
+ exit(EXIT_FAILURE);
}
uint bigswap(uint n)
{
- const int islittleendian = 1;
- return *(const uchar *)&islittleendian ? (n<<24) | (n>>24) | ((n>>8)&0xFF00) | ((n<<8)&0xFF0000) : n;
+ const int islittleendian = 1;
+ return *(const uchar *)&islittleendian ? (n<<24) | (n>>24) | ((n>>8)&0xFF00) | ((n<<8)&0xFF0000) : n;
}
size_t writebig(FILE *f, uint n)
{
- n = bigswap(n);
- return fwrite(&n, 1, sizeof(n), f);
+ n = bigswap(n);
+ return fwrite(&n, 1, sizeof(n), f);
}
void writepngchunk(FILE *f, const char *type, uchar *data, uint len)
{
- uint crc;
- writebig(f, len);
- fwrite(type, 1, 4, f);
- fwrite(data, 1, len, f);
-
- crc = crc32(0, Z_NULL, 0);
- crc = crc32(crc, (const Bytef *)type, 4);
- if(data) crc = crc32(crc, data, len);
- writebig(f, crc);
+ uint crc;
+ writebig(f, len);
+ fwrite(type, 1, 4, f);
+ fwrite(data, 1, len, f);
+
+ crc = crc32(0, Z_NULL, 0);
+ crc = crc32(crc, (const Bytef *)type, 4);
+ if(data) crc = crc32(crc, data, len);
+ writebig(f, crc);
}
struct pngihdr
{
- uint width, height;
- uchar bitdepth, colortype, compress, filter, interlace;
+ uint width, height;
+ uchar bitdepth, colortype, compress, filter, interlace;
};
void savepng(const char *filename, uchar *data, int w, int h, int bpp, int flip)
{
- const uchar signature[] = { 137, 80, 78, 71, 13, 10, 26, 10 };
- struct pngihdr ihdr;
- FILE *f;
- long idat;
- uint len, crc;
- z_stream z;
- uchar buf[1<<12];
- int i, j;
-
- memset(&ihdr, 0, sizeof(ihdr));
- ihdr.width = bigswap(w);
- ihdr.height = bigswap(h);
- ihdr.bitdepth = 8;
- switch(bpp)
- {
- case 1: ihdr.colortype = 0; break;
- case 2: ihdr.colortype = 4; break;
- case 3: ihdr.colortype = 2; break;
- case 4: ihdr.colortype = 6; break;
- default: fatal("cube2font: invalid PNG bpp"); return;
- }
- f = fopen(filename, "wb");
- if(!f) { fatal("cube2font: could not write to %s", filename); return; }
-
- fwrite(signature, 1, sizeof(signature), f);
-
- writepngchunk(f, "IHDR", (uchar *)&ihdr, 13);
-
- idat = ftell(f);
- len = 0;
- fwrite("\0\0\0\0IDAT", 1, 8, f);
- crc = crc32(0, Z_NULL, 0);
- crc = crc32(crc, (const Bytef *)"IDAT", 4);
-
- z.zalloc = NULL;
- z.zfree = NULL;
- z.opaque = NULL;
-
- if(deflateInit(&z, Z_BEST_COMPRESSION) != Z_OK)
- goto error;
-
- z.next_out = (Bytef *)buf;
- z.avail_out = sizeof(buf);
-
- for(i = 0; i < h; i++)
- {
- uchar filter = 0;
- for(j = 0; j < 2; j++)
- {
- z.next_in = j ? (Bytef *)data + (flip ? h-i-1 : i)*w*bpp : (Bytef *)&filter;
- z.avail_in = j ? w*bpp : 1;
- while(z.avail_in > 0)
- {
- if(deflate(&z, Z_NO_FLUSH) != Z_OK) goto cleanuperror;
- #define FLUSHZ do { \
- int flush = sizeof(buf) - z.avail_out; \
- crc = crc32(crc, buf, flush); \
- len += flush; \
- fwrite(buf, 1, flush, f); \
- z.next_out = (Bytef *)buf; \
- z.avail_out = sizeof(buf); \
- } while(0)
- FLUSHZ;
- }
- }
- }
-
- for(;;)
- {
- int err = deflate(&z, Z_FINISH);
- if(err != Z_OK && err != Z_STREAM_END) goto cleanuperror;
- FLUSHZ;
- if(err == Z_STREAM_END) break;
- }
-
- deflateEnd(&z);
-
- fseek(f, idat, SEEK_SET);
- writebig(f, len);
- fseek(f, 0, SEEK_END);
- writebig(f, crc);
-
- writepngchunk(f, "IEND", NULL, 0);
-
- fclose(f);
- return;
+ const uchar signature[] = { 137, 80, 78, 71, 13, 10, 26, 10 };
+ struct pngihdr ihdr;
+ FILE *f;
+ long idat;
+ uint len, crc;
+ z_stream z;
+ uchar buf[1<<12];
+ int i, j;
+
+ memset(&ihdr, 0, sizeof(ihdr));
+ ihdr.width = bigswap(w);
+ ihdr.height = bigswap(h);
+ ihdr.bitdepth = 8;
+ switch(bpp)
+ {
+ case 1: ihdr.colortype = 0; break;
+ case 2: ihdr.colortype = 4; break;
+ case 3: ihdr.colortype = 2; break;
+ case 4: ihdr.colortype = 6; break;
+ default: fatal("cube2font: invalid PNG bpp"); return;
+ }
+ f = fopen(filename, "wb");
+ if(!f) { fatal("cube2font: could not write to %s", filename); return; }
+
+ fwrite(signature, 1, sizeof(signature), f);
+
+ writepngchunk(f, "IHDR", (uchar *)&ihdr, 13);
+
+ idat = ftell(f);
+ len = 0;
+ fwrite("\0\0\0\0IDAT", 1, 8, f);
+ crc = crc32(0, Z_NULL, 0);
+ crc = crc32(crc, (const Bytef *)"IDAT", 4);
+
+ z.zalloc = NULL;
+ z.zfree = NULL;
+ z.opaque = NULL;
+
+ if(deflateInit(&z, Z_BEST_COMPRESSION) != Z_OK)
+ goto error;
+
+ z.next_out = (Bytef *)buf;
+ z.avail_out = sizeof(buf);
+
+ for(i = 0; i < h; i++)
+ {
+ uchar filter = 0;
+ for(j = 0; j < 2; j++)
+ {
+ z.next_in = j ? (Bytef *)data + (flip ? h-i-1 : i)*w*bpp : (Bytef *)&filter;
+ z.avail_in = j ? w*bpp : 1;
+ while(z.avail_in > 0)
+ {
+ if(deflate(&z, Z_NO_FLUSH) != Z_OK) goto cleanuperror;
+ #define FLUSHZ do { \
+ int flush = sizeof(buf) - z.avail_out; \
+ crc = crc32(crc, buf, flush); \
+ len += flush; \
+ fwrite(buf, 1, flush, f); \
+ z.next_out = (Bytef *)buf; \
+ z.avail_out = sizeof(buf); \
+ } while(0)
+ FLUSHZ;
+ }
+ }
+ }
+
+ for(;;)
+ {
+ int err = deflate(&z, Z_FINISH);
+ if(err != Z_OK && err != Z_STREAM_END) goto cleanuperror;
+ FLUSHZ;
+ if(err == Z_STREAM_END) break;
+ }
+
+ deflateEnd(&z);
+
+ fseek(f, idat, SEEK_SET);
+ writebig(f, len);
+ fseek(f, 0, SEEK_END);
+ writebig(f, crc);
+
+ writepngchunk(f, "IEND", NULL, 0);
+
+ fclose(f);
+ return;
cleanuperror:
- deflateEnd(&z);
+ deflateEnd(&z);
error:
- fclose(f);
+ fclose(f);
- fatal("cube2font: failed saving PNG to %s", filename);
+ fatal("cube2font: failed saving PNG to %s", filename);
}
enum
{
- CT_PRINT = 1<<0,
- CT_SPACE = 1<<1,
- CT_DIGIT = 1<<2,
- CT_ALPHA = 1<<3,
- CT_LOWER = 1<<4,
- CT_UPPER = 1<<5,
- CT_UNICODE = 1<<6
+ CT_PRINT = 1<<0,
+ CT_SPACE = 1<<1,
+ CT_DIGIT = 1<<2,
+ CT_ALPHA = 1<<3,
+ CT_LOWER = 1<<4,
+ CT_UPPER = 1<<5,
+ CT_UNICODE = 1<<6
};
#define CUBECTYPE(s, p, d, a, A, u, U) \
- 0, U, U, U, U, U, U, U, U, s, s, s, s, s, U, U, \
- U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, \
- s, p, p, p, p, p, p, p, p, p, p, p, p, p, p, p, \
- d, d, d, d, d, d, d, d, d, d, p, p, p, p, p, p, \
- p, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, \
- A, A, A, A, A, A, A, A, A, A, A, p, p, p, p, p, \
- p, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, \
- a, a, a, a, a, a, a, a, a, a, a, p, p, p, p, U, \
- U, u, u, u, u, u, u, u, u, u, u, u, u, u, u, u, \
- u, u, u, u, u, u, u, u, u, u, u, u, u, u, u, U, \
- u, U, u, U, u, U, u, U, u, U, u, U, u, U, u, U, \
- u, U, u, U, u, U, u, U, u, U, u, U, u, U, u, U, \
- u, U, u, U, u, U, u, U, U, u, U, u, U, u, U, U, \
- U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, \
- U, U, U, U, u, u, u, u, u, u, u, u, u, u, u, u, \
- u, u, u, u, u, u, u, u, u, u, u, u, u, u, U, u
+ 0, U, U, U, U, U, U, U, U, s, s, s, s, s, U, U, \
+ U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, \
+ s, p, p, p, p, p, p, p, p, p, p, p, p, p, p, p, \
+ d, d, d, d, d, d, d, d, d, d, p, p, p, p, p, p, \
+ p, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, \
+ A, A, A, A, A, A, A, A, A, A, A, p, p, p, p, p, \
+ p, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, \
+ a, a, a, a, a, a, a, a, a, a, a, p, p, p, p, U, \
+ U, u, u, u, u, u, u, u, u, u, u, u, u, u, u, u, \
+ u, u, u, u, u, u, u, u, u, u, u, u, u, u, u, U, \
+ u, U, u, U, u, U, u, U, u, U, u, U, u, U, u, U, \
+ u, U, u, U, u, U, u, U, u, U, u, U, u, U, u, U, \
+ u, U, u, U, u, U, u, U, U, u, U, u, U, u, U, U, \
+ U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, \
+ U, U, U, U, u, u, u, u, u, u, u, u, u, u, u, u, \
+ u, u, u, u, u, u, u, u, u, u, u, u, u, u, U, u
const uchar cubectype[256] =
{
- CUBECTYPE(CT_SPACE,
- CT_PRINT,
- CT_PRINT|CT_DIGIT,
- CT_PRINT|CT_ALPHA|CT_LOWER,
- CT_PRINT|CT_ALPHA|CT_UPPER,
- CT_PRINT|CT_UNICODE|CT_ALPHA|CT_LOWER,
- CT_PRINT|CT_UNICODE|CT_ALPHA|CT_UPPER)
+ CUBECTYPE(CT_SPACE,
+ CT_PRINT,
+ CT_PRINT|CT_DIGIT,
+ CT_PRINT|CT_ALPHA|CT_LOWER,
+ CT_PRINT|CT_ALPHA|CT_UPPER,
+ CT_PRINT|CT_UNICODE|CT_ALPHA|CT_LOWER,
+ CT_PRINT|CT_UNICODE|CT_ALPHA|CT_UPPER)
};
int iscubeprint(uchar c) { return cubectype[c]&CT_PRINT; }
int iscubespace(uchar c) { return cubectype[c]&CT_SPACE; }
@@ -201,46 +201,46 @@ int iscubelower(uchar c) { return cubectype[c]&CT_LOWER; }
int iscubeupper(uchar c) { return cubectype[c]&CT_UPPER; }
const int cube2unichars[256] =
{
- 0, 192, 193, 194, 195, 196, 197, 198, 199, 9, 10, 11, 12, 13, 200, 201,
- 202, 203, 204, 205, 206, 207, 209, 210, 211, 212, 213, 214, 216, 217, 218, 219,
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
- 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
- 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
- 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
- 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 220,
- 221, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237,
- 238, 239, 241, 242, 243, 244, 245, 246, 248, 249, 250, 251, 252, 253, 255, 0x104,
- 0x105, 0x106, 0x107, 0x10C, 0x10D, 0x10E, 0x10F, 0x118, 0x119, 0x11A, 0x11B, 0x11E, 0x11F, 0x130, 0x131, 0x141,
- 0x142, 0x143, 0x144, 0x147, 0x148, 0x150, 0x151, 0x152, 0x153, 0x158, 0x159, 0x15A, 0x15B, 0x15E, 0x15F, 0x160,
- 0x161, 0x164, 0x165, 0x16E, 0x16F, 0x170, 0x171, 0x178, 0x179, 0x17A, 0x17B, 0x17C, 0x17D, 0x17E, 0x404, 0x411,
- 0x413, 0x414, 0x416, 0x417, 0x418, 0x419, 0x41B, 0x41F, 0x423, 0x424, 0x426, 0x427, 0x428, 0x429, 0x42A, 0x42B,
- 0x42C, 0x42D, 0x42E, 0x42F, 0x431, 0x432, 0x433, 0x434, 0x436, 0x437, 0x438, 0x439, 0x43A, 0x43B, 0x43C, 0x43D,
- 0x43F, 0x442, 0x444, 0x446, 0x447, 0x448, 0x449, 0x44A, 0x44B, 0x44C, 0x44D, 0x44E, 0x44F, 0x454, 0x490, 0x491
+ 0, 192, 193, 194, 195, 196, 197, 198, 199, 9, 10, 11, 12, 13, 200, 201,
+ 202, 203, 204, 205, 206, 207, 209, 210, 211, 212, 213, 214, 216, 217, 218, 219,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
+ 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 220,
+ 221, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237,
+ 238, 239, 241, 242, 243, 244, 245, 246, 248, 249, 250, 251, 252, 253, 255, 0x104,
+ 0x105, 0x106, 0x107, 0x10C, 0x10D, 0x10E, 0x10F, 0x118, 0x119, 0x11A, 0x11B, 0x11E, 0x11F, 0x130, 0x131, 0x141,
+ 0x142, 0x143, 0x144, 0x147, 0x148, 0x150, 0x151, 0x152, 0x153, 0x158, 0x159, 0x15A, 0x15B, 0x15E, 0x15F, 0x160,
+ 0x161, 0x164, 0x165, 0x16E, 0x16F, 0x170, 0x171, 0x178, 0x179, 0x17A, 0x17B, 0x17C, 0x17D, 0x17E, 0x404, 0x411,
+ 0x413, 0x414, 0x416, 0x417, 0x418, 0x419, 0x41B, 0x41F, 0x423, 0x424, 0x426, 0x427, 0x428, 0x429, 0x42A, 0x42B,
+ 0x42C, 0x42D, 0x42E, 0x42F, 0x431, 0x432, 0x433, 0x434, 0x436, 0x437, 0x438, 0x439, 0x43A, 0x43B, 0x43C, 0x43D,
+ 0x43F, 0x442, 0x444, 0x446, 0x447, 0x448, 0x449, 0x44A, 0x44B, 0x44C, 0x44D, 0x44E, 0x44F, 0x454, 0x490, 0x491
};
int cube2uni(uchar c)
{
- return cube2unichars[c];
+ return cube2unichars[c];
}
const char *encodeutf8(int uni)
{
- static char buf[7];
- char *dst = buf;
- if(uni <= 0x7F) { *dst++ = uni; goto uni1; }
- else if(uni <= 0x7FF) { *dst++ = 0xC0 | (uni>>6); goto uni2; }
- else if(uni <= 0xFFFF) { *dst++ = 0xE0 | (uni>>12); goto uni3; }
- else if(uni <= 0x1FFFFF) { *dst++ = 0xF0 | (uni>>18); goto uni4; }
- else if(uni <= 0x3FFFFFF) { *dst++ = 0xF8 | (uni>>24); goto uni5; }
- else if(uni <= 0x7FFFFFFF) { *dst++ = 0xFC | (uni>>30); goto uni6; }
- else goto uni1;
+ static char buf[7];
+ char *dst = buf;
+ if(uni <= 0x7F) { *dst++ = uni; goto uni1; }
+ else if(uni <= 0x7FF) { *dst++ = 0xC0 | (uni>>6); goto uni2; }
+ else if(uni <= 0xFFFF) { *dst++ = 0xE0 | (uni>>12); goto uni3; }
+ else if(uni <= 0x1FFFFF) { *dst++ = 0xF0 | (uni>>18); goto uni4; }
+ else if(uni <= 0x3FFFFFF) { *dst++ = 0xF8 | (uni>>24); goto uni5; }
+ else if(uni <= 0x7FFFFFFF) { *dst++ = 0xFC | (uni>>30); goto uni6; }
+ else goto uni1;
uni6: *dst++ = 0x80 | ((uni>>24)&0x3F);
uni5: *dst++ = 0x80 | ((uni>>18)&0x3F);
uni4: *dst++ = 0x80 | ((uni>>12)&0x3F);
uni3: *dst++ = 0x80 | ((uni>>6)&0x3F);
uni2: *dst++ = 0x80 | (uni&0x3F);
uni1: *dst++ = '\0';
- return buf;
+ return buf;
}
struct fontchar { int code, uni, tex, x, y, w, h, offx, offy, offset, advance; FT_BitmapGlyph color, alpha; };
@@ -249,308 +249,308 @@ const char *texdir = "";
const char *texfilename(const char *name, int texnum)
{
- static char file[256];
- snprintf(file, sizeof(file), "%s%d.png", name, texnum);
- return file;
+ static char file[256];
+ snprintf(file, sizeof(file), "%s%d.png", name, texnum);
+ return file;
}
const char *texname(const char *name, int texnum)
{
- static char file[512];
- snprintf(file, sizeof(file), "<grey>%s%s", texdir, texfilename(name, texnum));
- return file;
+ static char file[512];
+ snprintf(file, sizeof(file), "<grey>%s%s", texdir, texfilename(name, texnum));
+ return file;
}
void writetexs(const char *name, struct fontchar *chars, int numchars, int numtexs, int tw, int th)
{
- int tex;
- uchar *pixels = (uchar *)malloc(tw*th*2);
- if(!pixels) fatal("cube2font: failed allocating textures");
- for(tex = 0; tex < numtexs; tex++)
- {
- const char *file = texfilename(name, tex);
- int texchars = 0, i;
- uchar *dst, *src;
- memset(pixels, 0, tw*th*2);
- for(i = 0; i < numchars; i++)
- {
- struct fontchar *c = &chars[i];
- int x, y;
- if(c->tex != tex) continue;
- texchars++;
- dst = &pixels[2*((c->y + c->offy - c->color->top)*tw + c->x + c->color->left - c->offx)];
- src = (uchar *)c->color->bitmap.buffer;
- for(y = 0; y < c->color->bitmap.rows; y++)
- {
- for(x = 0; x < c->color->bitmap.width; x++)
- dst[2*x] = src[x];
- src += c->color->bitmap.pitch;
- dst += 2*tw;
- }
- dst = &pixels[2*((c->y + c->offy - c->alpha->top)*tw + c->x + c->alpha->left - c->offx)];
- src = (uchar *)c->alpha->bitmap.buffer;
- for(y = 0; y < c->alpha->bitmap.rows; y++)
- {
- for(x = 0; x < c->alpha->bitmap.width; x++)
- dst[2*x+1] = src[x];
- src += c->alpha->bitmap.pitch;
- dst += 2*tw;
- }
- }
- printf("cube2font: writing %d chars to %s\n", texchars, file);
- savepng(file, pixels, tw, th, 2, 0);
+ int tex;
+ uchar *pixels = (uchar *)malloc(tw*th*2);
+ if(!pixels) fatal("cube2font: failed allocating textures");
+ for(tex = 0; tex < numtexs; tex++)
+ {
+ const char *file = texfilename(name, tex);
+ int texchars = 0, i;
+ uchar *dst, *src;
+ memset(pixels, 0, tw*th*2);
+ for(i = 0; i < numchars; i++)
+ {
+ struct fontchar *c = &chars[i];
+ int x, y;
+ if(c->tex != tex) continue;
+ texchars++;
+ dst = &pixels[2*((c->y + c->offy - c->color->top)*tw + c->x + c->color->left - c->offx)];
+ src = (uchar *)c->color->bitmap.buffer;
+ for(y = 0; y < c->color->bitmap.rows; y++)
+ {
+ for(x = 0; x < c->color->bitmap.width; x++)
+ dst[2*x] = src[x];
+ src += c->color->bitmap.pitch;
+ dst += 2*tw;
+ }
+ dst = &pixels[2*((c->y + c->offy - c->alpha->top)*tw + c->x + c->alpha->left - c->offx)];
+ src = (uchar *)c->alpha->bitmap.buffer;
+ for(y = 0; y < c->alpha->bitmap.rows; y++)
+ {
+ for(x = 0; x < c->alpha->bitmap.width; x++)
+ dst[2*x+1] = src[x];
+ src += c->alpha->bitmap.pitch;
+ dst += 2*tw;
+ }
+ }
+ printf("cube2font: writing %d chars to %s\n", texchars, file);
+ savepng(file, pixels, tw, th, 2, 0);
}
free(pixels);
}
void writecfg(const char *name, struct fontchar *chars, int numchars, int x1, int y1, int x2, int y2, int sw, int sh, int argc, char **argv)
{
- FILE *f;
- char file[256];
- int i, lastcode = 0, lasttex = 0;
- snprintf(file, sizeof(file), "%s.cfg", name);
- f = fopen(file, "w");
- if(!f) fatal("cube2font: failed writing %s", file);
- printf("cube2font: writing %d chars to %s\n", numchars, file);
- fprintf(f, "//");
- for(i = 1; i < argc; i++)
- fprintf(f, " %s", argv[i]);
- fprintf(f, "\n");
- fprintf(f, "font \"%s\" \"%s\" %d %d\n", name, texname(name, 0), sw, sh);
- for(i = 0; i < numchars; i++)
- {
- struct fontchar *c = &chars[i];
- if(!lastcode && lastcode < c->code)
- {
- fprintf(f, "fontoffset \"%s\"\n", encodeutf8(c->uni));
- lastcode = c->code;
- }
- else if(lastcode < c->code)
- {
- if(lastcode + 1 == c->code)
- fprintf(f, "fontskip // %d\n", lastcode);
- else
- fprintf(f, "fontskip %d // %d .. %d\n", c->code - lastcode, lastcode, c->code-1);
- lastcode = c->code;
- }
- if(lasttex != c->tex)
- {
- fprintf(f, "\nfonttex \"%s\"\n", texname(name, c->tex));
- lasttex = c->tex;
- }
- if(c->code != c->uni)
- fprintf(f, "fontchar %d %d %d %d %d %d %d // %s (%d -> 0x%X)\n", c->x, c->y, c->w, c->h, c->offx+c->offset, y2-c->offy, c->advance, encodeutf8(c->uni), c->code, c->uni);
- else
- fprintf(f, "fontchar %d %d %d %d %d %d %d // %s (%d)\n", c->x, c->y, c->w, c->h, c->offx+c->offset, y2-c->offy, c->advance, encodeutf8(c->uni), c->code);
- lastcode++;
- }
- fclose(f);
+ FILE *f;
+ char file[256];
+ int i, lastcode = 0, lasttex = 0;
+ snprintf(file, sizeof(file), "%s.cfg", name);
+ f = fopen(file, "w");
+ if(!f) fatal("cube2font: failed writing %s", file);
+ printf("cube2font: writing %d chars to %s\n", numchars, file);
+ fprintf(f, "//");
+ for(i = 1; i < argc; i++)
+ fprintf(f, " %s", argv[i]);
+ fprintf(f, "\n");
+ fprintf(f, "font \"%s\" \"%s\" %d %d\n", name, texname(name, 0), sw, sh);
+ for(i = 0; i < numchars; i++)
+ {
+ struct fontchar *c = &chars[i];
+ if(!lastcode && lastcode < c->code)
+ {
+ fprintf(f, "fontoffset \"%s\"\n", encodeutf8(c->uni));
+ lastcode = c->code;
+ }
+ else if(lastcode < c->code)
+ {
+ if(lastcode + 1 == c->code)
+ fprintf(f, "fontskip // %d\n", lastcode);
+ else
+ fprintf(f, "fontskip %d // %d .. %d\n", c->code - lastcode, lastcode, c->code-1);
+ lastcode = c->code;
+ }
+ if(lasttex != c->tex)
+ {
+ fprintf(f, "\nfonttex \"%s\"\n", texname(name, c->tex));
+ lasttex = c->tex;
+ }
+ if(c->code != c->uni)
+ fprintf(f, "fontchar %d %d %d %d %d %d %d // %s (%d -> 0x%X)\n", c->x, c->y, c->w, c->h, c->offx+c->offset, y2-c->offy, c->advance, encodeutf8(c->uni), c->code, c->uni);
+ else
+ fprintf(f, "fontchar %d %d %d %d %d %d %d // %s (%d)\n", c->x, c->y, c->w, c->h, c->offx+c->offset, y2-c->offy, c->advance, encodeutf8(c->uni), c->code);
+ lastcode++;
+ }
+ fclose(f);
}
int groupchar(int c)
{
- switch(c)
- {
- case 0x152: case 0x153: case 0x178: return 1;
- }
- if(c < 127 || c >= 0x2000) return 0;
- if(c < 0x100) return 1;
- if(c < 0x400) return 2;
- return 3;
+ switch(c)
+ {
+ case 0x152: case 0x153: case 0x178: return 1;
+ }
+ if(c < 127 || c >= 0x2000) return 0;
+ if(c < 0x100) return 1;
+ if(c < 0x400) return 2;
+ return 3;
}
int sortchars(const void *x, const void *y)
{
- const struct fontchar *xc = *(const struct fontchar **)x, *yc = *(const struct fontchar **)y;
- int xg = groupchar(xc->uni), yg = groupchar(yc->uni);
- if(xg < yg) return -1;
- if(xg > yg) return 1;
- if(xc->h != yc->h) return yc->h - xc->h;
- if(xc->w != yc->w) return yc->w - xc->w;
- return yc->uni - xc->uni;
+ const struct fontchar *xc = *(const struct fontchar **)x, *yc = *(const struct fontchar **)y;
+ int xg = groupchar(xc->uni), yg = groupchar(yc->uni);
+ if(xg < yg) return -1;
+ if(xg > yg) return 1;
+ if(xc->h != yc->h) return yc->h - xc->h;
+ if(xc->w != yc->w) return yc->w - xc->w;
+ return yc->uni - xc->uni;
}
int scorechar(struct fontchar *f, int pad, int tw, int th, int rw, int rh, int ry)
{
- int score = 0;
- if(rw + f->w > tw) { ry += rh + pad; score = 1; }
- if(ry + f->h > th) score = 2;
- return score;
+ int score = 0;
+ if(rw + f->w > tw) { ry += rh + pad; score = 1; }
+ if(ry + f->h > th) score = 2;
+ return score;
}
int main(int argc, char **argv)
{
- FT_Library l;
- FT_Face f;
- FT_Stroker s, s2;
- int i, pad, offset, advance, w, h, tw, th, c, trial = -2, rw = 0, rh = 0, ry = 0, x1 = INT_MAX, x2 = INT_MIN, y1 = INT_MAX, y2 = INT_MIN, w2 = 0, h2 = 0, sw = 0, sh = 0;
- float outborder = 0, inborder = 0;
- struct fontchar chars[256];
- struct fontchar *order[256];
- int numchars = 0, numtex = 0;
- if(argc < 11)
- fatal("Usage: cube2font infile outfile outborder[:inborder] pad offset advance charwidth charheight texwidth texheight [spacewidth spaceheight texdir]");
- sscanf(argv[3], "%f:%f", &outborder, &inborder);
- pad = atoi(argv[4]);
- offset = atoi(argv[5]);
- advance = atoi(argv[6]);
- w = atoi(argv[7]);
- h = atoi(argv[8]);
- tw = atoi(argv[9]);
- th = atoi(argv[10]);
- if(argc > 11) sw = atoi(argv[11]);
- if(argc > 12) sh = atoi(argv[12]);
- if(argc > 13) texdir = argv[13];
- if(FT_Init_FreeType(&l))
- fatal("cube2font: failed initing freetype");
- if(FT_New_Face(l, argv[1], 0, &f) ||
- FT_Set_Charmap(f, f->charmaps[0]) ||
- FT_Set_Pixel_Sizes(f, w, h) ||
- FT_Stroker_New(l, &s) ||
- FT_Stroker_New(l, &s2))
- fatal("cube2font: failed loading font %s", argv[1]);
- if(outborder > 0) FT_Stroker_Set(s, (FT_Fixed)(outborder * 64), FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0);
- if(inborder > 0) FT_Stroker_Set(s2, (FT_Fixed)(inborder * 64), FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0);
- for(c = 0; c < 256; c++) if(iscubeprint(c))
- {
- FT_Glyph p, p2;
- FT_BitmapGlyph b, b2;
- struct fontchar *dst = &chars[numchars];
- dst->code = c;
- dst->uni = cube2uni(c);
- if(FT_Load_Char(f, dst->uni, FT_LOAD_DEFAULT))
- fatal("cube2font: failed loading character %s", encodeutf8(dst->uni));
- FT_Get_Glyph(f->glyph, &p);
- p2 = p;
- if(outborder > 0) FT_Glyph_StrokeBorder(&p, s, 0, 0);
- if(inborder > 0) FT_Glyph_StrokeBorder(&p2, s2, 1, 0);
- FT_Glyph_To_Bitmap(&p, FT_RENDER_MODE_NORMAL, 0, 1);
- if(inborder > 0 || outborder > 0) FT_Glyph_To_Bitmap(&p2, FT_RENDER_MODE_NORMAL, 0, 1);
- else p2 = p;
- b = (FT_BitmapGlyph)p;
- b2 = (FT_BitmapGlyph)p2;
- dst->tex = -1;
- dst->x = INT_MIN;
- dst->y = INT_MIN;
- dst->offx = imin(b->left, b2->left);
- dst->offy = imax(b->top, b2->top);
- dst->offset = offset;
- dst->advance = offset + ((p->advance.x+0xFFFF)>>16) + advance;
- dst->w = imax(b->left + b->bitmap.width, b2->left + b2->bitmap.width) - dst->offx;
- dst->h = dst->offy - imin(b->top - b->bitmap.rows, b2->top - b2->bitmap.rows);
- dst->alpha = b;
- dst->color = b2;
- order[numchars++] = dst;
- }
- qsort(order, numchars, sizeof(order[0]), sortchars);
- for(i = 0; i < numchars;)
- {
- struct fontchar *dst;
- int j, k, trial0, prevscore, dstscore, fitscore;
- for(trial0 = trial, prevscore = -1; (trial -= 2) >= trial0-512;)
- {
- int g, fw = rw, fh = rh, fy = ry, curscore = 0, reused = 0;
- for(j = i; j < numchars; j++)
- {
- dst = order[j];
- if(dst->tex >= 0 || dst->tex <= trial) continue;
- g = groupchar(dst->uni);
- dstscore = scorechar(dst, pad, tw, th, fw, fh, fy);
- for(k = j; k < numchars; k++)
- {
- struct fontchar *fit = order[k];
- if(fit->tex >= 0 || fit->tex <= trial) continue;
- if(fit->tex >= trial0 && groupchar(fit->uni) != g) break;
- fitscore = scorechar(fit, pad, tw, th, fw, fh, fy);
- if(fitscore < dstscore || (fitscore == dstscore && fit->h > dst->h))
- {
- dst = fit;
- dstscore = fitscore;
- }
- }
- if(fw + dst->w > tw)
- {
- fy += fh + pad;
- fw = fh = 0;
- }
- if(fy + dst->h > th)
- {
- fy = fw = fh = 0;
- if(curscore > 0) break;
- }
- if(dst->tex >= trial+1 && dst->tex <= trial+2) { dst->tex = trial; reused++; }
- else dst->tex = trial;
- fw += dst->w + pad;
- fh = imax(fh, dst->h);
- if(dst != order[j]) --j;
- curscore++;
- }
- if(reused < prevscore || curscore <= prevscore) break;
- prevscore = curscore;
- }
- for(; i < numchars; i++)
- {
- dst = order[i];
- if(dst->tex >= 0) continue;
- dstscore = scorechar(dst, pad, tw, th, rw, rh, ry);
- for(j = i; j < numchars; j++)
- {
- struct fontchar *fit = order[j];
- if(fit->tex < trial || fit->tex > trial+2) continue;
- fitscore = scorechar(fit, pad, tw, th, rw, rh, ry);
- if(fitscore < dstscore || (fitscore == dstscore && fit->h > dst->h))
- {
- dst = fit;
- dstscore = fitscore;
- }
- }
- if(dst->tex < trial || dst->tex > trial+2) break;
- if(rw + dst->w > tw)
- {
- ry += rh + pad;
- rw = rh = 0;
- }
- if(ry + dst->h > th)
- {
- ry = rw = rh = 0;
- numtex++;
- }
- dst->tex = numtex;
- dst->x = rw;
- dst->y = ry;
- rw += dst->w + pad;
- rh = imax(rh, dst->h);
- y1 = imin(y1, dst->offy - dst->h);
- y2 = imax(y2, dst->offy);
- x1 = imin(x1, dst->offx);
- x2 = imax(x2, dst->offx + dst->w);
- w2 = imax(w2, dst->w);
- h2 = imax(h2, dst->h);
- if(dst != order[i]) --i;
- }
- }
- if(rh > 0) numtex++;
+ FT_Library l;
+ FT_Face f;
+ FT_Stroker s, s2;
+ int i, pad, offset, advance, w, h, tw, th, c, trial = -2, rw = 0, rh = 0, ry = 0, x1 = INT_MAX, x2 = INT_MIN, y1 = INT_MAX, y2 = INT_MIN, w2 = 0, h2 = 0, sw = 0, sh = 0;
+ float outborder = 0, inborder = 0;
+ struct fontchar chars[256];
+ struct fontchar *order[256];
+ int numchars = 0, numtex = 0;
+ if(argc < 11)
+ fatal("Usage: cube2font infile outfile outborder[:inborder] pad offset advance charwidth charheight texwidth texheight [spacewidth spaceheight texdir]");
+ sscanf(argv[3], "%f:%f", &outborder, &inborder);
+ pad = atoi(argv[4]);
+ offset = atoi(argv[5]);
+ advance = atoi(argv[6]);
+ w = atoi(argv[7]);
+ h = atoi(argv[8]);
+ tw = atoi(argv[9]);
+ th = atoi(argv[10]);
+ if(argc > 11) sw = atoi(argv[11]);
+ if(argc > 12) sh = atoi(argv[12]);
+ if(argc > 13) texdir = argv[13];
+ if(FT_Init_FreeType(&l))
+ fatal("cube2font: failed initing freetype");
+ if(FT_New_Face(l, argv[1], 0, &f) ||
+ FT_Set_Charmap(f, f->charmaps[0]) ||
+ FT_Set_Pixel_Sizes(f, w, h) ||
+ FT_Stroker_New(l, &s) ||
+ FT_Stroker_New(l, &s2))
+ fatal("cube2font: failed loading font %s", argv[1]);
+ if(outborder > 0) FT_Stroker_Set(s, (FT_Fixed)(outborder * 64), FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0);
+ if(inborder > 0) FT_Stroker_Set(s2, (FT_Fixed)(inborder * 64), FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0);
+ for(c = 0; c < 256; c++) if(iscubeprint(c))
+ {
+ FT_Glyph p, p2;
+ FT_BitmapGlyph b, b2;
+ struct fontchar *dst = &chars[numchars];
+ dst->code = c;
+ dst->uni = cube2uni(c);
+ if(FT_Load_Char(f, dst->uni, FT_LOAD_DEFAULT))
+ fatal("cube2font: failed loading character %s", encodeutf8(dst->uni));
+ FT_Get_Glyph(f->glyph, &p);
+ p2 = p;
+ if(outborder > 0) FT_Glyph_StrokeBorder(&p, s, 0, 0);
+ if(inborder > 0) FT_Glyph_StrokeBorder(&p2, s2, 1, 0);
+ FT_Glyph_To_Bitmap(&p, FT_RENDER_MODE_NORMAL, 0, 1);
+ if(inborder > 0 || outborder > 0) FT_Glyph_To_Bitmap(&p2, FT_RENDER_MODE_NORMAL, 0, 1);
+ else p2 = p;
+ b = (FT_BitmapGlyph)p;
+ b2 = (FT_BitmapGlyph)p2;
+ dst->tex = -1;
+ dst->x = INT_MIN;
+ dst->y = INT_MIN;
+ dst->offx = imin(b->left, b2->left);
+ dst->offy = imax(b->top, b2->top);
+ dst->offset = offset;
+ dst->advance = offset + ((p->advance.x+0xFFFF)>>16) + advance;
+ dst->w = imax(b->left + b->bitmap.width, b2->left + b2->bitmap.width) - dst->offx;
+ dst->h = dst->offy - imin(b->top - b->bitmap.rows, b2->top - b2->bitmap.rows);
+ dst->alpha = b;
+ dst->color = b2;
+ order[numchars++] = dst;
+ }
+ qsort(order, numchars, sizeof(order[0]), sortchars);
+ for(i = 0; i < numchars;)
+ {
+ struct fontchar *dst;
+ int j, k, trial0, prevscore, dstscore, fitscore;
+ for(trial0 = trial, prevscore = -1; (trial -= 2) >= trial0-512;)
+ {
+ int g, fw = rw, fh = rh, fy = ry, curscore = 0, reused = 0;
+ for(j = i; j < numchars; j++)
+ {
+ dst = order[j];
+ if(dst->tex >= 0 || dst->tex <= trial) continue;
+ g = groupchar(dst->uni);
+ dstscore = scorechar(dst, pad, tw, th, fw, fh, fy);
+ for(k = j; k < numchars; k++)
+ {
+ struct fontchar *fit = order[k];
+ if(fit->tex >= 0 || fit->tex <= trial) continue;
+ if(fit->tex >= trial0 && groupchar(fit->uni) != g) break;
+ fitscore = scorechar(fit, pad, tw, th, fw, fh, fy);
+ if(fitscore < dstscore || (fitscore == dstscore && fit->h > dst->h))
+ {
+ dst = fit;
+ dstscore = fitscore;
+ }
+ }
+ if(fw + dst->w > tw)
+ {
+ fy += fh + pad;
+ fw = fh = 0;
+ }
+ if(fy + dst->h > th)
+ {
+ fy = fw = fh = 0;
+ if(curscore > 0) break;
+ }
+ if(dst->tex >= trial+1 && dst->tex <= trial+2) { dst->tex = trial; reused++; }
+ else dst->tex = trial;
+ fw += dst->w + pad;
+ fh = imax(fh, dst->h);
+ if(dst != order[j]) --j;
+ curscore++;
+ }
+ if(reused < prevscore || curscore <= prevscore) break;
+ prevscore = curscore;
+ }
+ for(; i < numchars; i++)
+ {
+ dst = order[i];
+ if(dst->tex >= 0) continue;
+ dstscore = scorechar(dst, pad, tw, th, rw, rh, ry);
+ for(j = i; j < numchars; j++)
+ {
+ struct fontchar *fit = order[j];
+ if(fit->tex < trial || fit->tex > trial+2) continue;
+ fitscore = scorechar(fit, pad, tw, th, rw, rh, ry);
+ if(fitscore < dstscore || (fitscore == dstscore && fit->h > dst->h))
+ {
+ dst = fit;
+ dstscore = fitscore;
+ }
+ }
+ if(dst->tex < trial || dst->tex > trial+2) break;
+ if(rw + dst->w > tw)
+ {
+ ry += rh + pad;
+ rw = rh = 0;
+ }
+ if(ry + dst->h > th)
+ {
+ ry = rw = rh = 0;
+ numtex++;
+ }
+ dst->tex = numtex;
+ dst->x = rw;
+ dst->y = ry;
+ rw += dst->w + pad;
+ rh = imax(rh, dst->h);
+ y1 = imin(y1, dst->offy - dst->h);
+ y2 = imax(y2, dst->offy);
+ x1 = imin(x1, dst->offx);
+ x2 = imax(x2, dst->offx + dst->w);
+ w2 = imax(w2, dst->w);
+ h2 = imax(h2, dst->h);
+ if(dst != order[i]) --i;
+ }
+ }
+ if(rh > 0) numtex++;
#if 0
- if(sw <= 0)
- {
- if(FT_Load_Char(f, ' ', FT_LOAD_DEFAULT))
- fatal("cube2font: failed loading space character");
- sw = (f->glyph->advance.x+0x3F)>>6;
- }
+ if(sw <= 0)
+ {
+ if(FT_Load_Char(f, ' ', FT_LOAD_DEFAULT))
+ fatal("cube2font: failed loading space character");
+ sw = (f->glyph->advance.x+0x3F)>>6;
+ }
#endif
- if(sh <= 0) sh = y2 - y1;
- if(sw <= 0) sw = sh/3;
- writetexs(argv[2], chars, numchars, numtex, tw, th);
- writecfg(argv[2], chars, numchars, x1, y1, x2, y2, sw, sh, argc, argv);
- for(i = 0; i < numchars; i++)
- {
- if(chars[i].alpha != chars[i].color) FT_Done_Glyph((FT_Glyph)chars[i].alpha);
- FT_Done_Glyph((FT_Glyph)chars[i].color);
- }
- FT_Stroker_Done(s);
- FT_Stroker_Done(s2);
- FT_Done_FreeType(l);
- printf("cube2font: (%d, %d) .. (%d, %d) = (%d, %d) / (%d, %d), %d texs\n", x1, y1, x2, y2, x2 - x1, y2 - y1, w2, h2, numtex);
- return EXIT_SUCCESS;
+ if(sh <= 0) sh = y2 - y1;
+ if(sw <= 0) sw = sh/3;
+ writetexs(argv[2], chars, numchars, numtex, tw, th);
+ writecfg(argv[2], chars, numchars, x1, y1, x2, y2, sw, sh, argc, argv);
+ for(i = 0; i < numchars; i++)
+ {
+ if(chars[i].alpha != chars[i].color) FT_Done_Glyph((FT_Glyph)chars[i].alpha);
+ FT_Done_Glyph((FT_Glyph)chars[i].color);
+ }
+ FT_Stroker_Done(s);
+ FT_Stroker_Done(s2);
+ FT_Done_FreeType(l);
+ printf("cube2font: (%d, %d) .. (%d, %d) = (%d, %d) / (%d, %d), %d texs\n", x1, y1, x2, y2, x2 - x1, y2 - y1, w2, h2, numtex);
+ return EXIT_SUCCESS;
}
diff --git a/src/shared/ents.h b/src/shared/ents.h
index 91ccd8f..ac6fa39 100644
--- a/src/shared/ents.h
+++ b/src/shared/ents.h
@@ -5,57 +5,57 @@
enum { ET_EMPTY=0, ET_LIGHT, ET_MAPMODEL, ET_PLAYERSTART, ET_ENVMAP, ET_PARTICLES, ET_SOUND, ET_SPOTLIGHT, ET_GAMESPECIFIC };
-struct entity // persistent map entity
+struct entity // persistent map entity
{
- vec o; // position
- short attr1, attr2, attr3, attr4, attr5;
- uchar type; // type is one of the above
- uchar reserved;
+ vec o; // position
+ short attr1, attr2, attr3, attr4, attr5;
+ uchar type; // type is one of the above
+ uchar reserved;
};
struct entitylight
{
- vec color, dir;
- int millis;
+ vec color, dir;
+ int millis;
- entitylight() : color(1, 1, 1), dir(0, 0, 1), millis(-1) {}
+ entitylight() : color(1, 1, 1), dir(0, 0, 1), millis(-1) {}
};
enum
{
- EF_NOVIS = 1<<0,
- EF_NOSHADOW = 1<<1,
- EF_NOCOLLIDE = 1<<2,
- EF_ANIM = 1<<3,
- EF_OCTA = 1<<4,
- EF_RENDER = 1<<5,
- EF_SOUND = 1<<6,
- EF_SPAWNED = 1<<7,
- EF_NOPICKUP = 1<<8
+ EF_NOVIS = 1<<0,
+ EF_NOSHADOW = 1<<1,
+ EF_NOCOLLIDE = 1<<2,
+ EF_ANIM = 1<<3,
+ EF_OCTA = 1<<4,
+ EF_RENDER = 1<<5,
+ EF_SOUND = 1<<6,
+ EF_SPAWNED = 1<<7,
+ EF_NOPICKUP = 1<<8
};
-struct extentity : entity // part of the entity that doesn't get saved to disk
+struct extentity : entity // part of the entity that doesn't get saved to disk
{
- int flags; // the only dynamic state of a map entity
- entitylight light;
- extentity *attached;
+ int flags; // the only dynamic state of a map entity
+ entitylight light;
+ extentity *attached;
- extentity() : flags(0), attached(NULL) {}
+ extentity() : flags(0), attached(NULL) {}
- bool spawned() const { return (flags&EF_SPAWNED) != 0; }
- void setspawned(bool val) { if(val) flags |= EF_SPAWNED; else flags &= ~EF_SPAWNED; }
- void setspawned() { flags |= EF_SPAWNED; }
- void clearspawned() { flags &= ~EF_SPAWNED; }
+ bool spawned() const { return (flags&EF_SPAWNED) != 0; }
+ void setspawned(bool val) { if(val) flags |= EF_SPAWNED; else flags &= ~EF_SPAWNED; }
+ void setspawned() { flags |= EF_SPAWNED; }
+ void clearspawned() { flags &= ~EF_SPAWNED; }
- bool nopickup() const { return (flags&EF_NOPICKUP) != 0; }
- void setnopickup(bool val) { if(val) flags |= EF_NOPICKUP; else flags &= ~EF_NOPICKUP; }
- void setnopickup() { flags |= EF_NOPICKUP; }
- void clearnopickup() { flags &= ~EF_NOPICKUP; }
+ bool nopickup() const { return (flags&EF_NOPICKUP) != 0; }
+ void setnopickup(bool val) { if(val) flags |= EF_NOPICKUP; else flags &= ~EF_NOPICKUP; }
+ void setnopickup() { flags |= EF_NOPICKUP; }
+ void clearnopickup() { flags &= ~EF_NOPICKUP; }
};
#define MAXENTS 10000
-//extern vector<extentity *> ents; // map entities
+//extern vector<extentity *> ents; // map entities
enum { CS_ALIVE = 0, CS_DEAD, CS_SPAWNING, CS_LAGGED, CS_EDITING, CS_SPECTATOR };
@@ -65,128 +65,128 @@ enum { ENT_PLAYER = 0, ENT_AI, ENT_INANIMATE, ENT_CAMERA, ENT_BOUNCE };
enum { COLLIDE_NONE = 0, COLLIDE_ELLIPSE, COLLIDE_OBB, COLLIDE_ELLIPSE_PRECISE };
-struct physent // base entity type, can be affected by physics
+struct physent // base entity type, can be affected by physics
{
- vec o, vel, falling; // origin, velocity
- vec deltapos, newpos; // movement interpolation
- float yaw, pitch, roll;
- float maxspeed; // cubes per second, 100 for player
- float radius, eyeheight, aboveeye; // bounding box size
- float xradius, yradius, zmargin;
- vec floor; // the normal of floor the dynent is on
-
- ushort timeinair;
- uchar inwater;
- bool jumping;
- schar move, strafe;
-
- uchar physstate; // one of PHYS_* above
- uchar state, editstate; // one of CS_* above
- uchar type; // one of ENT_* above
- uchar collidetype; // one of COLLIDE_* above
-
- bool blocked; // used by physics to signal ai
-
- physent() : o(0, 0, 0), deltapos(0, 0, 0), newpos(0, 0, 0), yaw(0), pitch(0), roll(0), maxspeed(100),
- radius(4.1f), eyeheight(14), aboveeye(1), xradius(4.1f), yradius(4.1f), zmargin(0),
- state(CS_ALIVE), editstate(CS_ALIVE), type(ENT_PLAYER),
- collidetype(COLLIDE_ELLIPSE),
- blocked(false)
- { reset(); }
-
- void resetinterp()
- {
- newpos = o;
- deltapos = vec(0, 0, 0);
- }
-
- void reset()
- {
- inwater = 0;
- timeinair = 0;
- jumping = false;
- strafe = move = 0;
- physstate = PHYS_FALL;
- vel = falling = vec(0, 0, 0);
- floor = vec(0, 0, 1);
- }
-
- vec feetpos(float offset = 0) const { return vec(o).add(vec(0, 0, offset - eyeheight)); }
- vec headpos(float offset = 0) const { return vec(o).add(vec(0, 0, offset)); }
-
- bool maymove() const { return timeinair || physstate < PHYS_FLOOR || vel.squaredlen() > 1e-4f || deltapos.squaredlen() > 1e-4f; }
+ vec o, vel, falling; // origin, velocity
+ vec deltapos, newpos; // movement interpolation
+ float yaw, pitch, roll;
+ float maxspeed; // cubes per second, 100 for player
+ float radius, eyeheight, aboveeye; // bounding box size
+ float xradius, yradius, zmargin;
+ vec floor; // the normal of floor the dynent is on
+
+ ushort timeinair;
+ uchar inwater;
+ bool jumping;
+ schar move, strafe;
+
+ uchar physstate; // one of PHYS_* above
+ uchar state, editstate; // one of CS_* above
+ uchar type; // one of ENT_* above
+ uchar collidetype; // one of COLLIDE_* above
+
+ bool blocked; // used by physics to signal ai
+
+ physent() : o(0, 0, 0), deltapos(0, 0, 0), newpos(0, 0, 0), yaw(0), pitch(0), roll(0), maxspeed(100),
+ radius(4.1f), eyeheight(14), aboveeye(1), xradius(4.1f), yradius(4.1f), zmargin(0),
+ state(CS_ALIVE), editstate(CS_ALIVE), type(ENT_PLAYER),
+ collidetype(COLLIDE_ELLIPSE),
+ blocked(false)
+ { reset(); }
+
+ void resetinterp()
+ {
+ newpos = o;
+ deltapos = vec(0, 0, 0);
+ }
+
+ void reset()
+ {
+ inwater = 0;
+ timeinair = 0;
+ jumping = false;
+ strafe = move = 0;
+ physstate = PHYS_FALL;
+ vel = falling = vec(0, 0, 0);
+ floor = vec(0, 0, 1);
+ }
+
+ vec feetpos(float offset = 0) const { return vec(o).add(vec(0, 0, offset - eyeheight)); }
+ vec headpos(float offset = 0) const { return vec(o).add(vec(0, 0, offset)); }
+
+ bool maymove() const { return timeinair || physstate < PHYS_FLOOR || vel.squaredlen() > 1e-4f || deltapos.squaredlen() > 1e-4f; }
};
enum
{
- ANIM_DEAD = 0, ANIM_DYING, ANIM_IDLE,
- ANIM_FORWARD, ANIM_BACKWARD, ANIM_LEFT, ANIM_RIGHT,
- ANIM_HOLD1, ANIM_HOLD2, ANIM_HOLD3, ANIM_HOLD4, ANIM_HOLD5, ANIM_HOLD6, ANIM_HOLD7,
- ANIM_ATTACK1, ANIM_ATTACK2, ANIM_ATTACK3, ANIM_ATTACK4, ANIM_ATTACK5, ANIM_ATTACK6, ANIM_ATTACK7,
- ANIM_PAIN,
- ANIM_JUMP, ANIM_SINK, ANIM_SWIM,
- ANIM_EDIT, ANIM_LAG, ANIM_TAUNT, ANIM_WIN, ANIM_LOSE,
- ANIM_GUN_IDLE, ANIM_GUN_SHOOT,
- ANIM_VWEP_IDLE, ANIM_VWEP_SHOOT, ANIM_SHIELD, ANIM_POWERUP,
- ANIM_MAPMODEL,
- NUMANIMS
+ ANIM_DEAD = 0, ANIM_DYING, ANIM_IDLE,
+ ANIM_FORWARD, ANIM_BACKWARD, ANIM_LEFT, ANIM_RIGHT,
+ ANIM_HOLD1, ANIM_HOLD2, ANIM_HOLD3, ANIM_HOLD4, ANIM_HOLD5, ANIM_HOLD6, ANIM_HOLD7,
+ ANIM_ATTACK1, ANIM_ATTACK2, ANIM_ATTACK3, ANIM_ATTACK4, ANIM_ATTACK5, ANIM_ATTACK6, ANIM_ATTACK7,
+ ANIM_PAIN,
+ ANIM_JUMP, ANIM_SINK, ANIM_SWIM,
+ ANIM_EDIT, ANIM_LAG, ANIM_TAUNT, ANIM_WIN, ANIM_LOSE,
+ ANIM_GUN_IDLE, ANIM_GUN_SHOOT,
+ ANIM_VWEP_IDLE, ANIM_VWEP_SHOOT, ANIM_SHIELD, ANIM_POWERUP,
+ ANIM_MAPMODEL,
+ NUMANIMS
};
static const char * const animnames[] =
{
- "dead", "dying", "idle",
- "forward", "backward", "left", "right",
- "hold 1", "hold 2", "hold 3", "hold 4", "hold 5", "hold 6", "hold 7",
- "attack 1", "attack 2", "attack 3", "attack 4", "attack 5", "attack 6", "attack 7",
- "pain",
- "jump", "sink", "swim",
- "edit", "lag", "taunt", "win", "lose",
- "gun idle", "gun shoot",
- "vwep idle", "vwep shoot", "shield", "powerup",
- "mapmodel"
+ "dead", "dying", "idle",
+ "forward", "backward", "left", "right",
+ "hold 1", "hold 2", "hold 3", "hold 4", "hold 5", "hold 6", "hold 7",
+ "attack 1", "attack 2", "attack 3", "attack 4", "attack 5", "attack 6", "attack 7",
+ "pain",
+ "jump", "sink", "swim",
+ "edit", "lag", "taunt", "win", "lose",
+ "gun idle", "gun shoot",
+ "vwep idle", "vwep shoot", "shield", "powerup",
+ "mapmodel"
};
-#define ANIM_ALL 0x7F
-#define ANIM_INDEX 0x7F
-#define ANIM_LOOP (1<<7)
-#define ANIM_START (1<<8)
-#define ANIM_END (1<<9)
-#define ANIM_REVERSE (1<<10)
-#define ANIM_CLAMP (ANIM_START|ANIM_END)
-#define ANIM_DIR 0x780
+#define ANIM_ALL 0x7F
+#define ANIM_INDEX 0x7F
+#define ANIM_LOOP (1<<7)
+#define ANIM_START (1<<8)
+#define ANIM_END (1<<9)
+#define ANIM_REVERSE (1<<10)
+#define ANIM_CLAMP (ANIM_START|ANIM_END)
+#define ANIM_DIR 0x780
#define ANIM_SECONDARY 11
-#define ANIM_NOSKIN (1<<22)
-#define ANIM_SETTIME (1<<23)
+#define ANIM_NOSKIN (1<<22)
+#define ANIM_SETTIME (1<<23)
#define ANIM_FULLBRIGHT (1<<24)
-#define ANIM_REUSE (1<<25)
-#define ANIM_NORENDER (1<<26)
-#define ANIM_RAGDOLL (1<<27)
-#define ANIM_SETSPEED (1<<28)
-#define ANIM_NOPITCH (1<<29)
-#define ANIM_GHOST (1<<30)
-#define ANIM_FLAGS (0x1FF<<22)
+#define ANIM_REUSE (1<<25)
+#define ANIM_NORENDER (1<<26)
+#define ANIM_RAGDOLL (1<<27)
+#define ANIM_SETSPEED (1<<28)
+#define ANIM_NOPITCH (1<<29)
+#define ANIM_GHOST (1<<30)
+#define ANIM_FLAGS (0x1FF<<22)
struct animinfo // description of a character's animation
{
- int anim, frame, range, basetime;
- float speed;
- uint varseed;
+ int anim, frame, range, basetime;
+ float speed;
+ uint varseed;
- animinfo() : anim(0), frame(0), range(0), basetime(0), speed(100.0f), varseed(0) { }
+ animinfo() : anim(0), frame(0), range(0), basetime(0), speed(100.0f), varseed(0) { }
- bool operator==(const animinfo &o) const { return frame==o.frame && range==o.range && (anim&(ANIM_SETTIME|ANIM_DIR))==(o.anim&(ANIM_SETTIME|ANIM_DIR)) && (anim&ANIM_SETTIME || basetime==o.basetime) && speed==o.speed; }
- bool operator!=(const animinfo &o) const { return frame!=o.frame || range!=o.range || (anim&(ANIM_SETTIME|ANIM_DIR))!=(o.anim&(ANIM_SETTIME|ANIM_DIR)) || (!(anim&ANIM_SETTIME) && basetime!=o.basetime) || speed!=o.speed; }
+ bool operator==(const animinfo &o) const { return frame==o.frame && range==o.range && (anim&(ANIM_SETTIME|ANIM_DIR))==(o.anim&(ANIM_SETTIME|ANIM_DIR)) && (anim&ANIM_SETTIME || basetime==o.basetime) && speed==o.speed; }
+ bool operator!=(const animinfo &o) const { return frame!=o.frame || range!=o.range || (anim&(ANIM_SETTIME|ANIM_DIR))!=(o.anim&(ANIM_SETTIME|ANIM_DIR)) || (!(anim&ANIM_SETTIME) && basetime!=o.basetime) || speed!=o.speed; }
};
struct animinterpinfo // used for animation blending of animated characters
{
- animinfo prev, cur;
- int lastswitch;
- void *lastmodel;
+ animinfo prev, cur;
+ int lastswitch;
+ void *lastmodel;
- animinterpinfo() : lastswitch(-1), lastmodel(NULL) {}
+ animinterpinfo() : lastswitch(-1), lastmodel(NULL) {}
- void reset() { lastswitch = -1; }
+ void reset() { lastswitch = -1; }
};
#define MAXANIMPARTS 3
@@ -194,44 +194,44 @@ struct animinterpinfo // used for animation blending of animated characters
struct occludequery;
struct ragdolldata;
-struct dynent : physent // animated characters, or characters that can receive input
+struct dynent : physent // animated characters, or characters that can receive input
{
- bool k_left, k_right, k_up, k_down; // see input code
-
- entitylight light;
- animinterpinfo animinterp[MAXANIMPARTS];
- ragdolldata *ragdoll;
- occludequery *query;
- int lastrendered;
- uchar occluded;
-
- dynent() : ragdoll(NULL), query(NULL), lastrendered(0), occluded(0)
- {
- reset();
- }
-
- ~dynent()
- {
+ bool k_left, k_right, k_up, k_down; // see input code
+
+ entitylight light;
+ animinterpinfo animinterp[MAXANIMPARTS];
+ ragdolldata *ragdoll;
+ occludequery *query;
+ int lastrendered;
+ uchar occluded;
+
+ dynent() : ragdoll(NULL), query(NULL), lastrendered(0), occluded(0)
+ {
+ reset();
+ }
+
+ ~dynent()
+ {
#ifndef STANDALONE
- extern void cleanragdoll(dynent *d);
- if(ragdoll) cleanragdoll(this);
+ extern void cleanragdoll(dynent *d);
+ if(ragdoll) cleanragdoll(this);
#endif
- }
-
- void stopmoving()
- {
- k_left = k_right = k_up = k_down = jumping = false;
- move = strafe = 0;
- }
-
- void reset()
- {
- physent::reset();
- stopmoving();
- loopi(MAXANIMPARTS) animinterp[i].reset();
- }
-
- vec abovehead() { return vec(o).add(vec(0, 0, aboveeye+4)); }
+ }
+
+ void stopmoving()
+ {
+ k_left = k_right = k_up = k_down = jumping = false;
+ move = strafe = 0;
+ }
+
+ void reset()
+ {
+ physent::reset();
+ stopmoving();
+ loopi(MAXANIMPARTS) animinterp[i].reset();
+ }
+
+ vec abovehead() { return vec(o).add(vec(0, 0, aboveeye+4)); }
};
diff --git a/src/shared/geom.cpp b/src/shared/geom.cpp
index 43206e1..a5192e4 100644
--- a/src/shared/geom.cpp
+++ b/src/shared/geom.cpp
@@ -3,255 +3,255 @@
static inline double det2x2(double a, double b, double c, double d) { return a*d - b*c; }
static inline double det3x3(double a1, double a2, double a3,
- double b1, double b2, double b3,
- double c1, double c2, double c3)
+ double b1, double b2, double b3,
+ double c1, double c2, double c3)
{
- return a1 * det2x2(b2, b3, c2, c3)
- - b1 * det2x2(a2, a3, c2, c3)
- + c1 * det2x2(a2, a3, b2, b3);
+ return a1 * det2x2(b2, b3, c2, c3)
+ - b1 * det2x2(a2, a3, c2, c3)
+ + c1 * det2x2(a2, a3, b2, b3);
}
bool matrix4::invert(const matrix4 &m, double mindet)
{
- double a1 = m.a.x, a2 = m.a.y, a3 = m.a.z, a4 = m.a.w,
- b1 = m.b.x, b2 = m.b.y, b3 = m.b.z, b4 = m.b.w,
- c1 = m.c.x, c2 = m.c.y, c3 = m.c.z, c4 = m.c.w,
- d1 = m.d.x, d2 = m.d.y, d3 = m.d.z, d4 = m.d.w,
- det1 = det3x3(b2, b3, b4, c2, c3, c4, d2, d3, d4),
- det2 = -det3x3(a2, a3, a4, c2, c3, c4, d2, d3, d4),
- det3 = det3x3(a2, a3, a4, b2, b3, b4, d2, d3, d4),
- det4 = -det3x3(a2, a3, a4, b2, b3, b4, c2, c3, c4),
- det = a1*det1 + b1*det2 + c1*det3 + d1*det4;
+ double a1 = m.a.x, a2 = m.a.y, a3 = m.a.z, a4 = m.a.w,
+ b1 = m.b.x, b2 = m.b.y, b3 = m.b.z, b4 = m.b.w,
+ c1 = m.c.x, c2 = m.c.y, c3 = m.c.z, c4 = m.c.w,
+ d1 = m.d.x, d2 = m.d.y, d3 = m.d.z, d4 = m.d.w,
+ det1 = det3x3(b2, b3, b4, c2, c3, c4, d2, d3, d4),
+ det2 = -det3x3(a2, a3, a4, c2, c3, c4, d2, d3, d4),
+ det3 = det3x3(a2, a3, a4, b2, b3, b4, d2, d3, d4),
+ det4 = -det3x3(a2, a3, a4, b2, b3, b4, c2, c3, c4),
+ det = a1*det1 + b1*det2 + c1*det3 + d1*det4;
- if(fabs(det) < mindet) return false;
+ if(fabs(det) < mindet) return false;
- double invdet = 1/det;
+ double invdet = 1/det;
- a.x = det1 * invdet;
- a.y = det2 * invdet;
- a.z = det3 * invdet;
- a.w = det4 * invdet;
+ a.x = det1 * invdet;
+ a.y = det2 * invdet;
+ a.z = det3 * invdet;
+ a.w = det4 * invdet;
- b.x = -det3x3(b1, b3, b4, c1, c3, c4, d1, d3, d4) * invdet;
- b.y = det3x3(a1, a3, a4, c1, c3, c4, d1, d3, d4) * invdet;
- b.z = -det3x3(a1, a3, a4, b1, b3, b4, d1, d3, d4) * invdet;
- b.w = det3x3(a1, a3, a4, b1, b3, b4, c1, c3, c4) * invdet;
+ b.x = -det3x3(b1, b3, b4, c1, c3, c4, d1, d3, d4) * invdet;
+ b.y = det3x3(a1, a3, a4, c1, c3, c4, d1, d3, d4) * invdet;
+ b.z = -det3x3(a1, a3, a4, b1, b3, b4, d1, d3, d4) * invdet;
+ b.w = det3x3(a1, a3, a4, b1, b3, b4, c1, c3, c4) * invdet;
- c.x = det3x3(b1, b2, b4, c1, c2, c4, d1, d2, d4) * invdet;
- c.y = -det3x3(a1, a2, a4, c1, c2, c4, d1, d2, d4) * invdet;
- c.z = det3x3(a1, a2, a4, b1, b2, b4, d1, d2, d4) * invdet;
- c.w = -det3x3(a1, a2, a4, b1, b2, b4, c1, c2, c4) * invdet;
+ c.x = det3x3(b1, b2, b4, c1, c2, c4, d1, d2, d4) * invdet;
+ c.y = -det3x3(a1, a2, a4, c1, c2, c4, d1, d2, d4) * invdet;
+ c.z = det3x3(a1, a2, a4, b1, b2, b4, d1, d2, d4) * invdet;
+ c.w = -det3x3(a1, a2, a4, b1, b2, b4, c1, c2, c4) * invdet;
- d.x = -det3x3(b1, b2, b3, c1, c2, c3, d1, d2, d3) * invdet;
- d.y = det3x3(a1, a2, a3, c1, c2, c3, d1, d2, d3) * invdet;
- d.z = -det3x3(a1, a2, a3, b1, b2, b3, d1, d2, d3) * invdet;
- d.w = det3x3(a1, a2, a3, b1, b2, b3, c1, c2, c3) * invdet;
+ d.x = -det3x3(b1, b2, b3, c1, c2, c3, d1, d2, d3) * invdet;
+ d.y = det3x3(a1, a2, a3, c1, c2, c3, d1, d2, d3) * invdet;
+ d.z = -det3x3(a1, a2, a3, b1, b2, b3, d1, d2, d3) * invdet;
+ d.w = det3x3(a1, a2, a3, b1, b2, b3, c1, c2, c3) * invdet;
- return true;
+ return true;
}
bool raysphereintersect(const vec &center, float radius, const vec &o, const vec &ray, float &dist)
{
- vec c(center);
- c.sub(o);
- float v = c.dot(ray),
- inside = radius*radius - c.squaredlen();
- if(inside<0 && v<0) return false;
- float d = inside + v*v;
- if(d<0) return false;
- dist = v - sqrt(d);
- return true;
+ vec c(center);
+ c.sub(o);
+ float v = c.dot(ray),
+ inside = radius*radius - c.squaredlen();
+ if(inside<0 && v<0) return false;
+ float d = inside + v*v;
+ if(d<0) return false;
+ dist = v - sqrt(d);
+ return true;
}
bool rayboxintersect(const vec &b, const vec &s, const vec &o, const vec &ray, float &dist, int &orient)
{
- loop(d, 3) if(ray[d])
- {
- int dc = ray[d]<0 ? 1 : 0;
- float pdist = (b[d]+s[d]*dc - o[d]) / ray[d];
- vec v(ray);
- v.mul(pdist).add(o);
- if(v[R[d]] >= b[R[d]] && v[R[d]] <= b[R[d]]+s[R[d]]
- && v[C[d]] >= b[C[d]] && v[C[d]] <= b[C[d]]+s[C[d]])
- {
- dist = pdist;
- orient = 2*d+dc;
- return true;
- }
- }
- return false;
+ loop(d, 3) if(ray[d])
+ {
+ int dc = ray[d]<0 ? 1 : 0;
+ float pdist = (b[d]+s[d]*dc - o[d]) / ray[d];
+ vec v(ray);
+ v.mul(pdist).add(o);
+ if(v[R[d]] >= b[R[d]] && v[R[d]] <= b[R[d]]+s[R[d]]
+ && v[C[d]] >= b[C[d]] && v[C[d]] <= b[C[d]]+s[C[d]])
+ {
+ dist = pdist;
+ orient = 2*d+dc;
+ return true;
+ }
+ }
+ return false;
}
bool linecylinderintersect(const vec &from, const vec &to, const vec &start, const vec &end, float radius, float &dist)
{
- vec d(end), m(from), n(to);
- d.sub(start);
- m.sub(start);
- n.sub(from);
- float md = m.dot(d),
- nd = n.dot(d),
- dd = d.squaredlen();
- if(md < 0 && md + nd < 0) return false;
- if(md > dd && md + nd > dd) return false;
- float nn = n.squaredlen(),
- mn = m.dot(n),
- a = dd*nn - nd*nd,
- k = m.squaredlen() - radius*radius,
- c = dd*k - md*md;
- if(fabs(a) < 0.005f)
- {
- if(c > 0) return false;
- if(md < 0) dist = -mn / nn;
- else if(md > dd) dist = (nd - mn) / nn;
- else dist = 0;
- return true;
- }
- else if(c > 0)
- {
- float b = dd*mn - nd*md,
- discrim = b*b - a*c;
- if(discrim < 0) return false;
- dist = (-b - sqrtf(discrim)) / a;
- }
- else dist = 0;
- float offset = md + dist*nd;
- if(offset < 0)
- {
- if(nd <= 0) return false;
- dist = -md / nd;
- if(k + dist*(2*mn + dist*nn) > 0) return false;
- }
- else if(offset > dd)
- {
- if(nd >= 0) return false;
- dist = (dd - md) / nd;
- if(k + dd - 2*md + dist*(2*(mn-nd) + dist*nn) > 0) return false;
- }
- return dist >= 0 && dist <= 1;
+ vec d(end), m(from), n(to);
+ d.sub(start);
+ m.sub(start);
+ n.sub(from);
+ float md = m.dot(d),
+ nd = n.dot(d),
+ dd = d.squaredlen();
+ if(md < 0 && md + nd < 0) return false;
+ if(md > dd && md + nd > dd) return false;
+ float nn = n.squaredlen(),
+ mn = m.dot(n),
+ a = dd*nn - nd*nd,
+ k = m.squaredlen() - radius*radius,
+ c = dd*k - md*md;
+ if(fabs(a) < 0.005f)
+ {
+ if(c > 0) return false;
+ if(md < 0) dist = -mn / nn;
+ else if(md > dd) dist = (nd - mn) / nn;
+ else dist = 0;
+ return true;
+ }
+ else if(c > 0)
+ {
+ float b = dd*mn - nd*md,
+ discrim = b*b - a*c;
+ if(discrim < 0) return false;
+ dist = (-b - sqrtf(discrim)) / a;
+ }
+ else dist = 0;
+ float offset = md + dist*nd;
+ if(offset < 0)
+ {
+ if(nd <= 0) return false;
+ dist = -md / nd;
+ if(k + dist*(2*mn + dist*nn) > 0) return false;
+ }
+ else if(offset > dd)
+ {
+ if(nd >= 0) return false;
+ dist = (dd - md) / nd;
+ if(k + dd - 2*md + dist*(2*(mn-nd) + dist*nn) > 0) return false;
+ }
+ return dist >= 0 && dist <= 1;
}
extern const vec2 sincos360[721] =
{
- vec2(1.00000000, 0.00000000), vec2(0.99984770, 0.01745241), vec2(0.99939083, 0.03489950), vec2(0.99862953, 0.05233596), vec2(0.99756405, 0.06975647), vec2(0.99619470, 0.08715574), // 0
- vec2(0.99452190, 0.10452846), vec2(0.99254615, 0.12186934), vec2(0.99026807, 0.13917310), vec2(0.98768834, 0.15643447), vec2(0.98480775, 0.17364818), vec2(0.98162718, 0.19080900), // 6
- vec2(0.97814760, 0.20791169), vec2(0.97437006, 0.22495105), vec2(0.97029573, 0.24192190), vec2(0.96592583, 0.25881905), vec2(0.96126170, 0.27563736), vec2(0.95630476, 0.29237170), // 12
- vec2(0.95105652, 0.30901699), vec2(0.94551858, 0.32556815), vec2(0.93969262, 0.34202014), vec2(0.93358043, 0.35836795), vec2(0.92718385, 0.37460659), vec2(0.92050485, 0.39073113), // 18
- vec2(0.91354546, 0.40673664), vec2(0.90630779, 0.42261826), vec2(0.89879405, 0.43837115), vec2(0.89100652, 0.45399050), vec2(0.88294759, 0.46947156), vec2(0.87461971, 0.48480962), // 24
- vec2(0.86602540, 0.50000000), vec2(0.85716730, 0.51503807), vec2(0.84804810, 0.52991926), vec2(0.83867057, 0.54463904), vec2(0.82903757, 0.55919290), vec2(0.81915204, 0.57357644), // 30
- vec2(0.80901699, 0.58778525), vec2(0.79863551, 0.60181502), vec2(0.78801075, 0.61566148), vec2(0.77714596, 0.62932039), vec2(0.76604444, 0.64278761), vec2(0.75470958, 0.65605903), // 36
- vec2(0.74314483, 0.66913061), vec2(0.73135370, 0.68199836), vec2(0.71933980, 0.69465837), vec2(0.70710678, 0.70710678), vec2(0.69465837, 0.71933980), vec2(0.68199836, 0.73135370), // 42
- vec2(0.66913061, 0.74314483), vec2(0.65605903, 0.75470958), vec2(0.64278761, 0.76604444), vec2(0.62932039, 0.77714596), vec2(0.61566148, 0.78801075), vec2(0.60181502, 0.79863551), // 48
- vec2(0.58778525, 0.80901699), vec2(0.57357644, 0.81915204), vec2(0.55919290, 0.82903757), vec2(0.54463904, 0.83867057), vec2(0.52991926, 0.84804810), vec2(0.51503807, 0.85716730), // 54
- vec2(0.50000000, 0.86602540), vec2(0.48480962, 0.87461971), vec2(0.46947156, 0.88294759), vec2(0.45399050, 0.89100652), vec2(0.43837115, 0.89879405), vec2(0.42261826, 0.90630779), // 60
- vec2(0.40673664, 0.91354546), vec2(0.39073113, 0.92050485), vec2(0.37460659, 0.92718385), vec2(0.35836795, 0.93358043), vec2(0.34202014, 0.93969262), vec2(0.32556815, 0.94551858), // 66
- vec2(0.30901699, 0.95105652), vec2(0.29237170, 0.95630476), vec2(0.27563736, 0.96126170), vec2(0.25881905, 0.96592583), vec2(0.24192190, 0.97029573), vec2(0.22495105, 0.97437006), // 72
- vec2(0.20791169, 0.97814760), vec2(0.19080900, 0.98162718), vec2(0.17364818, 0.98480775), vec2(0.15643447, 0.98768834), vec2(0.13917310, 0.99026807), vec2(0.12186934, 0.99254615), // 78
- vec2(0.10452846, 0.99452190), vec2(0.08715574, 0.99619470), vec2(0.06975647, 0.99756405), vec2(0.05233596, 0.99862953), vec2(0.03489950, 0.99939083), vec2(0.01745241, 0.99984770), // 84
- vec2(0.00000000, 1.00000000), vec2(-0.01745241, 0.99984770), vec2(-0.03489950, 0.99939083), vec2(-0.05233596, 0.99862953), vec2(-0.06975647, 0.99756405), vec2(-0.08715574, 0.99619470), // 90
- vec2(-0.10452846, 0.99452190), vec2(-0.12186934, 0.99254615), vec2(-0.13917310, 0.99026807), vec2(-0.15643447, 0.98768834), vec2(-0.17364818, 0.98480775), vec2(-0.19080900, 0.98162718), // 96
- vec2(-0.20791169, 0.97814760), vec2(-0.22495105, 0.97437006), vec2(-0.24192190, 0.97029573), vec2(-0.25881905, 0.96592583), vec2(-0.27563736, 0.96126170), vec2(-0.29237170, 0.95630476), // 102
- vec2(-0.30901699, 0.95105652), vec2(-0.32556815, 0.94551858), vec2(-0.34202014, 0.93969262), vec2(-0.35836795, 0.93358043), vec2(-0.37460659, 0.92718385), vec2(-0.39073113, 0.92050485), // 108
- vec2(-0.40673664, 0.91354546), vec2(-0.42261826, 0.90630779), vec2(-0.43837115, 0.89879405), vec2(-0.45399050, 0.89100652), vec2(-0.46947156, 0.88294759), vec2(-0.48480962, 0.87461971), // 114
- vec2(-0.50000000, 0.86602540), vec2(-0.51503807, 0.85716730), vec2(-0.52991926, 0.84804810), vec2(-0.54463904, 0.83867057), vec2(-0.55919290, 0.82903757), vec2(-0.57357644, 0.81915204), // 120
- vec2(-0.58778525, 0.80901699), vec2(-0.60181502, 0.79863551), vec2(-0.61566148, 0.78801075), vec2(-0.62932039, 0.77714596), vec2(-0.64278761, 0.76604444), vec2(-0.65605903, 0.75470958), // 126
- vec2(-0.66913061, 0.74314483), vec2(-0.68199836, 0.73135370), vec2(-0.69465837, 0.71933980), vec2(-0.70710678, 0.70710678), vec2(-0.71933980, 0.69465837), vec2(-0.73135370, 0.68199836), // 132
- vec2(-0.74314483, 0.66913061), vec2(-0.75470958, 0.65605903), vec2(-0.76604444, 0.64278761), vec2(-0.77714596, 0.62932039), vec2(-0.78801075, 0.61566148), vec2(-0.79863551, 0.60181502), // 138
- vec2(-0.80901699, 0.58778525), vec2(-0.81915204, 0.57357644), vec2(-0.82903757, 0.55919290), vec2(-0.83867057, 0.54463904), vec2(-0.84804810, 0.52991926), vec2(-0.85716730, 0.51503807), // 144
- vec2(-0.86602540, 0.50000000), vec2(-0.87461971, 0.48480962), vec2(-0.88294759, 0.46947156), vec2(-0.89100652, 0.45399050), vec2(-0.89879405, 0.43837115), vec2(-0.90630779, 0.42261826), // 150
- vec2(-0.91354546, 0.40673664), vec2(-0.92050485, 0.39073113), vec2(-0.92718385, 0.37460659), vec2(-0.93358043, 0.35836795), vec2(-0.93969262, 0.34202014), vec2(-0.94551858, 0.32556815), // 156
- vec2(-0.95105652, 0.30901699), vec2(-0.95630476, 0.29237170), vec2(-0.96126170, 0.27563736), vec2(-0.96592583, 0.25881905), vec2(-0.97029573, 0.24192190), vec2(-0.97437006, 0.22495105), // 162
- vec2(-0.97814760, 0.20791169), vec2(-0.98162718, 0.19080900), vec2(-0.98480775, 0.17364818), vec2(-0.98768834, 0.15643447), vec2(-0.99026807, 0.13917310), vec2(-0.99254615, 0.12186934), // 168
- vec2(-0.99452190, 0.10452846), vec2(-0.99619470, 0.08715574), vec2(-0.99756405, 0.06975647), vec2(-0.99862953, 0.05233596), vec2(-0.99939083, 0.03489950), vec2(-0.99984770, 0.01745241), // 174
- vec2(-1.00000000, 0.00000000), vec2(-0.99984770, -0.01745241), vec2(-0.99939083, -0.03489950), vec2(-0.99862953, -0.05233596), vec2(-0.99756405, -0.06975647), vec2(-0.99619470, -0.08715574), // 180
- vec2(-0.99452190, -0.10452846), vec2(-0.99254615, -0.12186934), vec2(-0.99026807, -0.13917310), vec2(-0.98768834, -0.15643447), vec2(-0.98480775, -0.17364818), vec2(-0.98162718, -0.19080900), // 186
- vec2(-0.97814760, -0.20791169), vec2(-0.97437006, -0.22495105), vec2(-0.97029573, -0.24192190), vec2(-0.96592583, -0.25881905), vec2(-0.96126170, -0.27563736), vec2(-0.95630476, -0.29237170), // 192
- vec2(-0.95105652, -0.30901699), vec2(-0.94551858, -0.32556815), vec2(-0.93969262, -0.34202014), vec2(-0.93358043, -0.35836795), vec2(-0.92718385, -0.37460659), vec2(-0.92050485, -0.39073113), // 198
- vec2(-0.91354546, -0.40673664), vec2(-0.90630779, -0.42261826), vec2(-0.89879405, -0.43837115), vec2(-0.89100652, -0.45399050), vec2(-0.88294759, -0.46947156), vec2(-0.87461971, -0.48480962), // 204
- vec2(-0.86602540, -0.50000000), vec2(-0.85716730, -0.51503807), vec2(-0.84804810, -0.52991926), vec2(-0.83867057, -0.54463904), vec2(-0.82903757, -0.55919290), vec2(-0.81915204, -0.57357644), // 210
- vec2(-0.80901699, -0.58778525), vec2(-0.79863551, -0.60181502), vec2(-0.78801075, -0.61566148), vec2(-0.77714596, -0.62932039), vec2(-0.76604444, -0.64278761), vec2(-0.75470958, -0.65605903), // 216
- vec2(-0.74314483, -0.66913061), vec2(-0.73135370, -0.68199836), vec2(-0.71933980, -0.69465837), vec2(-0.70710678, -0.70710678), vec2(-0.69465837, -0.71933980), vec2(-0.68199836, -0.73135370), // 222
- vec2(-0.66913061, -0.74314483), vec2(-0.65605903, -0.75470958), vec2(-0.64278761, -0.76604444), vec2(-0.62932039, -0.77714596), vec2(-0.61566148, -0.78801075), vec2(-0.60181502, -0.79863551), // 228
- vec2(-0.58778525, -0.80901699), vec2(-0.57357644, -0.81915204), vec2(-0.55919290, -0.82903757), vec2(-0.54463904, -0.83867057), vec2(-0.52991926, -0.84804810), vec2(-0.51503807, -0.85716730), // 234
- vec2(-0.50000000, -0.86602540), vec2(-0.48480962, -0.87461971), vec2(-0.46947156, -0.88294759), vec2(-0.45399050, -0.89100652), vec2(-0.43837115, -0.89879405), vec2(-0.42261826, -0.90630779), // 240
- vec2(-0.40673664, -0.91354546), vec2(-0.39073113, -0.92050485), vec2(-0.37460659, -0.92718385), vec2(-0.35836795, -0.93358043), vec2(-0.34202014, -0.93969262), vec2(-0.32556815, -0.94551858), // 246
- vec2(-0.30901699, -0.95105652), vec2(-0.29237170, -0.95630476), vec2(-0.27563736, -0.96126170), vec2(-0.25881905, -0.96592583), vec2(-0.24192190, -0.97029573), vec2(-0.22495105, -0.97437006), // 252
- vec2(-0.20791169, -0.97814760), vec2(-0.19080900, -0.98162718), vec2(-0.17364818, -0.98480775), vec2(-0.15643447, -0.98768834), vec2(-0.13917310, -0.99026807), vec2(-0.12186934, -0.99254615), // 258
- vec2(-0.10452846, -0.99452190), vec2(-0.08715574, -0.99619470), vec2(-0.06975647, -0.99756405), vec2(-0.05233596, -0.99862953), vec2(-0.03489950, -0.99939083), vec2(-0.01745241, -0.99984770), // 264
- vec2(-0.00000000, -1.00000000), vec2(0.01745241, -0.99984770), vec2(0.03489950, -0.99939083), vec2(0.05233596, -0.99862953), vec2(0.06975647, -0.99756405), vec2(0.08715574, -0.99619470), // 270
- vec2(0.10452846, -0.99452190), vec2(0.12186934, -0.99254615), vec2(0.13917310, -0.99026807), vec2(0.15643447, -0.98768834), vec2(0.17364818, -0.98480775), vec2(0.19080900, -0.98162718), // 276
- vec2(0.20791169, -0.97814760), vec2(0.22495105, -0.97437006), vec2(0.24192190, -0.97029573), vec2(0.25881905, -0.96592583), vec2(0.27563736, -0.96126170), vec2(0.29237170, -0.95630476), // 282
- vec2(0.30901699, -0.95105652), vec2(0.32556815, -0.94551858), vec2(0.34202014, -0.93969262), vec2(0.35836795, -0.93358043), vec2(0.37460659, -0.92718385), vec2(0.39073113, -0.92050485), // 288
- vec2(0.40673664, -0.91354546), vec2(0.42261826, -0.90630779), vec2(0.43837115, -0.89879405), vec2(0.45399050, -0.89100652), vec2(0.46947156, -0.88294759), vec2(0.48480962, -0.87461971), // 294
- vec2(0.50000000, -0.86602540), vec2(0.51503807, -0.85716730), vec2(0.52991926, -0.84804810), vec2(0.54463904, -0.83867057), vec2(0.55919290, -0.82903757), vec2(0.57357644, -0.81915204), // 300
- vec2(0.58778525, -0.80901699), vec2(0.60181502, -0.79863551), vec2(0.61566148, -0.78801075), vec2(0.62932039, -0.77714596), vec2(0.64278761, -0.76604444), vec2(0.65605903, -0.75470958), // 306
- vec2(0.66913061, -0.74314483), vec2(0.68199836, -0.73135370), vec2(0.69465837, -0.71933980), vec2(0.70710678, -0.70710678), vec2(0.71933980, -0.69465837), vec2(0.73135370, -0.68199836), // 312
- vec2(0.74314483, -0.66913061), vec2(0.75470958, -0.65605903), vec2(0.76604444, -0.64278761), vec2(0.77714596, -0.62932039), vec2(0.78801075, -0.61566148), vec2(0.79863551, -0.60181502), // 318
- vec2(0.80901699, -0.58778525), vec2(0.81915204, -0.57357644), vec2(0.82903757, -0.55919290), vec2(0.83867057, -0.54463904), vec2(0.84804810, -0.52991926), vec2(0.85716730, -0.51503807), // 324
- vec2(0.86602540, -0.50000000), vec2(0.87461971, -0.48480962), vec2(0.88294759, -0.46947156), vec2(0.89100652, -0.45399050), vec2(0.89879405, -0.43837115), vec2(0.90630779, -0.42261826), // 330
- vec2(0.91354546, -0.40673664), vec2(0.92050485, -0.39073113), vec2(0.92718385, -0.37460659), vec2(0.93358043, -0.35836795), vec2(0.93969262, -0.34202014), vec2(0.94551858, -0.32556815), // 336
- vec2(0.95105652, -0.30901699), vec2(0.95630476, -0.29237170), vec2(0.96126170, -0.27563736), vec2(0.96592583, -0.25881905), vec2(0.97029573, -0.24192190), vec2(0.97437006, -0.22495105), // 342
- vec2(0.97814760, -0.20791169), vec2(0.98162718, -0.19080900), vec2(0.98480775, -0.17364818), vec2(0.98768834, -0.15643447), vec2(0.99026807, -0.13917310), vec2(0.99254615, -0.12186934), // 348
- vec2(0.99452190, -0.10452846), vec2(0.99619470, -0.08715574), vec2(0.99756405, -0.06975647), vec2(0.99862953, -0.05233596), vec2(0.99939083, -0.03489950), vec2(0.99984770, -0.01745241), // 354
- vec2(1.00000000, 0.00000000), vec2(0.99984770, 0.01745241), vec2(0.99939083, 0.03489950), vec2(0.99862953, 0.05233596), vec2(0.99756405, 0.06975647), vec2(0.99619470, 0.08715574), // 360
- vec2(0.99452190, 0.10452846), vec2(0.99254615, 0.12186934), vec2(0.99026807, 0.13917310), vec2(0.98768834, 0.15643447), vec2(0.98480775, 0.17364818), vec2(0.98162718, 0.19080900), // 366
- vec2(0.97814760, 0.20791169), vec2(0.97437006, 0.22495105), vec2(0.97029573, 0.24192190), vec2(0.96592583, 0.25881905), vec2(0.96126170, 0.27563736), vec2(0.95630476, 0.29237170), // 372
- vec2(0.95105652, 0.30901699), vec2(0.94551858, 0.32556815), vec2(0.93969262, 0.34202014), vec2(0.93358043, 0.35836795), vec2(0.92718385, 0.37460659), vec2(0.92050485, 0.39073113), // 378
- vec2(0.91354546, 0.40673664), vec2(0.90630779, 0.42261826), vec2(0.89879405, 0.43837115), vec2(0.89100652, 0.45399050), vec2(0.88294759, 0.46947156), vec2(0.87461971, 0.48480962), // 384
- vec2(0.86602540, 0.50000000), vec2(0.85716730, 0.51503807), vec2(0.84804810, 0.52991926), vec2(0.83867057, 0.54463904), vec2(0.82903757, 0.55919290), vec2(0.81915204, 0.57357644), // 390
- vec2(0.80901699, 0.58778525), vec2(0.79863551, 0.60181502), vec2(0.78801075, 0.61566148), vec2(0.77714596, 0.62932039), vec2(0.76604444, 0.64278761), vec2(0.75470958, 0.65605903), // 396
- vec2(0.74314483, 0.66913061), vec2(0.73135370, 0.68199836), vec2(0.71933980, 0.69465837), vec2(0.70710678, 0.70710678), vec2(0.69465837, 0.71933980), vec2(0.68199836, 0.73135370), // 402
- vec2(0.66913061, 0.74314483), vec2(0.65605903, 0.75470958), vec2(0.64278761, 0.76604444), vec2(0.62932039, 0.77714596), vec2(0.61566148, 0.78801075), vec2(0.60181502, 0.79863551), // 408
- vec2(0.58778525, 0.80901699), vec2(0.57357644, 0.81915204), vec2(0.55919290, 0.82903757), vec2(0.54463904, 0.83867057), vec2(0.52991926, 0.84804810), vec2(0.51503807, 0.85716730), // 414
- vec2(0.50000000, 0.86602540), vec2(0.48480962, 0.87461971), vec2(0.46947156, 0.88294759), vec2(0.45399050, 0.89100652), vec2(0.43837115, 0.89879405), vec2(0.42261826, 0.90630779), // 420
- vec2(0.40673664, 0.91354546), vec2(0.39073113, 0.92050485), vec2(0.37460659, 0.92718385), vec2(0.35836795, 0.93358043), vec2(0.34202014, 0.93969262), vec2(0.32556815, 0.94551858), // 426
- vec2(0.30901699, 0.95105652), vec2(0.29237170, 0.95630476), vec2(0.27563736, 0.96126170), vec2(0.25881905, 0.96592583), vec2(0.24192190, 0.97029573), vec2(0.22495105, 0.97437006), // 432
- vec2(0.20791169, 0.97814760), vec2(0.19080900, 0.98162718), vec2(0.17364818, 0.98480775), vec2(0.15643447, 0.98768834), vec2(0.13917310, 0.99026807), vec2(0.12186934, 0.99254615), // 438
- vec2(0.10452846, 0.99452190), vec2(0.08715574, 0.99619470), vec2(0.06975647, 0.99756405), vec2(0.05233596, 0.99862953), vec2(0.03489950, 0.99939083), vec2(0.01745241, 0.99984770), // 444
- vec2(0.00000000, 1.00000000), vec2(-0.01745241, 0.99984770), vec2(-0.03489950, 0.99939083), vec2(-0.05233596, 0.99862953), vec2(-0.06975647, 0.99756405), vec2(-0.08715574, 0.99619470), // 450
- vec2(-0.10452846, 0.99452190), vec2(-0.12186934, 0.99254615), vec2(-0.13917310, 0.99026807), vec2(-0.15643447, 0.98768834), vec2(-0.17364818, 0.98480775), vec2(-0.19080900, 0.98162718), // 456
- vec2(-0.20791169, 0.97814760), vec2(-0.22495105, 0.97437006), vec2(-0.24192190, 0.97029573), vec2(-0.25881905, 0.96592583), vec2(-0.27563736, 0.96126170), vec2(-0.29237170, 0.95630476), // 462
- vec2(-0.30901699, 0.95105652), vec2(-0.32556815, 0.94551858), vec2(-0.34202014, 0.93969262), vec2(-0.35836795, 0.93358043), vec2(-0.37460659, 0.92718385), vec2(-0.39073113, 0.92050485), // 468
- vec2(-0.40673664, 0.91354546), vec2(-0.42261826, 0.90630779), vec2(-0.43837115, 0.89879405), vec2(-0.45399050, 0.89100652), vec2(-0.46947156, 0.88294759), vec2(-0.48480962, 0.87461971), // 474
- vec2(-0.50000000, 0.86602540), vec2(-0.51503807, 0.85716730), vec2(-0.52991926, 0.84804810), vec2(-0.54463904, 0.83867057), vec2(-0.55919290, 0.82903757), vec2(-0.57357644, 0.81915204), // 480
- vec2(-0.58778525, 0.80901699), vec2(-0.60181502, 0.79863551), vec2(-0.61566148, 0.78801075), vec2(-0.62932039, 0.77714596), vec2(-0.64278761, 0.76604444), vec2(-0.65605903, 0.75470958), // 486
- vec2(-0.66913061, 0.74314483), vec2(-0.68199836, 0.73135370), vec2(-0.69465837, 0.71933980), vec2(-0.70710678, 0.70710678), vec2(-0.71933980, 0.69465837), vec2(-0.73135370, 0.68199836), // 492
- vec2(-0.74314483, 0.66913061), vec2(-0.75470958, 0.65605903), vec2(-0.76604444, 0.64278761), vec2(-0.77714596, 0.62932039), vec2(-0.78801075, 0.61566148), vec2(-0.79863551, 0.60181502), // 498
- vec2(-0.80901699, 0.58778525), vec2(-0.81915204, 0.57357644), vec2(-0.82903757, 0.55919290), vec2(-0.83867057, 0.54463904), vec2(-0.84804810, 0.52991926), vec2(-0.85716730, 0.51503807), // 504
- vec2(-0.86602540, 0.50000000), vec2(-0.87461971, 0.48480962), vec2(-0.88294759, 0.46947156), vec2(-0.89100652, 0.45399050), vec2(-0.89879405, 0.43837115), vec2(-0.90630779, 0.42261826), // 510
- vec2(-0.91354546, 0.40673664), vec2(-0.92050485, 0.39073113), vec2(-0.92718385, 0.37460659), vec2(-0.93358043, 0.35836795), vec2(-0.93969262, 0.34202014), vec2(-0.94551858, 0.32556815), // 516
- vec2(-0.95105652, 0.30901699), vec2(-0.95630476, 0.29237170), vec2(-0.96126170, 0.27563736), vec2(-0.96592583, 0.25881905), vec2(-0.97029573, 0.24192190), vec2(-0.97437006, 0.22495105), // 522
- vec2(-0.97814760, 0.20791169), vec2(-0.98162718, 0.19080900), vec2(-0.98480775, 0.17364818), vec2(-0.98768834, 0.15643447), vec2(-0.99026807, 0.13917310), vec2(-0.99254615, 0.12186934), // 528
- vec2(-0.99452190, 0.10452846), vec2(-0.99619470, 0.08715574), vec2(-0.99756405, 0.06975647), vec2(-0.99862953, 0.05233596), vec2(-0.99939083, 0.03489950), vec2(-0.99984770, 0.01745241), // 534
- vec2(-1.00000000, 0.00000000), vec2(-0.99984770, -0.01745241), vec2(-0.99939083, -0.03489950), vec2(-0.99862953, -0.05233596), vec2(-0.99756405, -0.06975647), vec2(-0.99619470, -0.08715574), // 540
- vec2(-0.99452190, -0.10452846), vec2(-0.99254615, -0.12186934), vec2(-0.99026807, -0.13917310), vec2(-0.98768834, -0.15643447), vec2(-0.98480775, -0.17364818), vec2(-0.98162718, -0.19080900), // 546
- vec2(-0.97814760, -0.20791169), vec2(-0.97437006, -0.22495105), vec2(-0.97029573, -0.24192190), vec2(-0.96592583, -0.25881905), vec2(-0.96126170, -0.27563736), vec2(-0.95630476, -0.29237170), // 552
- vec2(-0.95105652, -0.30901699), vec2(-0.94551858, -0.32556815), vec2(-0.93969262, -0.34202014), vec2(-0.93358043, -0.35836795), vec2(-0.92718385, -0.37460659), vec2(-0.92050485, -0.39073113), // 558
- vec2(-0.91354546, -0.40673664), vec2(-0.90630779, -0.42261826), vec2(-0.89879405, -0.43837115), vec2(-0.89100652, -0.45399050), vec2(-0.88294759, -0.46947156), vec2(-0.87461971, -0.48480962), // 564
- vec2(-0.86602540, -0.50000000), vec2(-0.85716730, -0.51503807), vec2(-0.84804810, -0.52991926), vec2(-0.83867057, -0.54463904), vec2(-0.82903757, -0.55919290), vec2(-0.81915204, -0.57357644), // 570
- vec2(-0.80901699, -0.58778525), vec2(-0.79863551, -0.60181502), vec2(-0.78801075, -0.61566148), vec2(-0.77714596, -0.62932039), vec2(-0.76604444, -0.64278761), vec2(-0.75470958, -0.65605903), // 576
- vec2(-0.74314483, -0.66913061), vec2(-0.73135370, -0.68199836), vec2(-0.71933980, -0.69465837), vec2(-0.70710678, -0.70710678), vec2(-0.69465837, -0.71933980), vec2(-0.68199836, -0.73135370), // 582
- vec2(-0.66913061, -0.74314483), vec2(-0.65605903, -0.75470958), vec2(-0.64278761, -0.76604444), vec2(-0.62932039, -0.77714596), vec2(-0.61566148, -0.78801075), vec2(-0.60181502, -0.79863551), // 588
- vec2(-0.58778525, -0.80901699), vec2(-0.57357644, -0.81915204), vec2(-0.55919290, -0.82903757), vec2(-0.54463904, -0.83867057), vec2(-0.52991926, -0.84804810), vec2(-0.51503807, -0.85716730), // 594
- vec2(-0.50000000, -0.86602540), vec2(-0.48480962, -0.87461971), vec2(-0.46947156, -0.88294759), vec2(-0.45399050, -0.89100652), vec2(-0.43837115, -0.89879405), vec2(-0.42261826, -0.90630779), // 600
- vec2(-0.40673664, -0.91354546), vec2(-0.39073113, -0.92050485), vec2(-0.37460659, -0.92718385), vec2(-0.35836795, -0.93358043), vec2(-0.34202014, -0.93969262), vec2(-0.32556815, -0.94551858), // 606
- vec2(-0.30901699, -0.95105652), vec2(-0.29237170, -0.95630476), vec2(-0.27563736, -0.96126170), vec2(-0.25881905, -0.96592583), vec2(-0.24192190, -0.97029573), vec2(-0.22495105, -0.97437006), // 612
- vec2(-0.20791169, -0.97814760), vec2(-0.19080900, -0.98162718), vec2(-0.17364818, -0.98480775), vec2(-0.15643447, -0.98768834), vec2(-0.13917310, -0.99026807), vec2(-0.12186934, -0.99254615), // 618
- vec2(-0.10452846, -0.99452190), vec2(-0.08715574, -0.99619470), vec2(-0.06975647, -0.99756405), vec2(-0.05233596, -0.99862953), vec2(-0.03489950, -0.99939083), vec2(-0.01745241, -0.99984770), // 624
- vec2(-0.00000000, -1.00000000), vec2(0.01745241, -0.99984770), vec2(0.03489950, -0.99939083), vec2(0.05233596, -0.99862953), vec2(0.06975647, -0.99756405), vec2(0.08715574, -0.99619470), // 630
- vec2(0.10452846, -0.99452190), vec2(0.12186934, -0.99254615), vec2(0.13917310, -0.99026807), vec2(0.15643447, -0.98768834), vec2(0.17364818, -0.98480775), vec2(0.19080900, -0.98162718), // 636
- vec2(0.20791169, -0.97814760), vec2(0.22495105, -0.97437006), vec2(0.24192190, -0.97029573), vec2(0.25881905, -0.96592583), vec2(0.27563736, -0.96126170), vec2(0.29237170, -0.95630476), // 642
- vec2(0.30901699, -0.95105652), vec2(0.32556815, -0.94551858), vec2(0.34202014, -0.93969262), vec2(0.35836795, -0.93358043), vec2(0.37460659, -0.92718385), vec2(0.39073113, -0.92050485), // 648
- vec2(0.40673664, -0.91354546), vec2(0.42261826, -0.90630779), vec2(0.43837115, -0.89879405), vec2(0.45399050, -0.89100652), vec2(0.46947156, -0.88294759), vec2(0.48480962, -0.87461971), // 654
- vec2(0.50000000, -0.86602540), vec2(0.51503807, -0.85716730), vec2(0.52991926, -0.84804810), vec2(0.54463904, -0.83867057), vec2(0.55919290, -0.82903757), vec2(0.57357644, -0.81915204), // 660
- vec2(0.58778525, -0.80901699), vec2(0.60181502, -0.79863551), vec2(0.61566148, -0.78801075), vec2(0.62932039, -0.77714596), vec2(0.64278761, -0.76604444), vec2(0.65605903, -0.75470958), // 666
- vec2(0.66913061, -0.74314483), vec2(0.68199836, -0.73135370), vec2(0.69465837, -0.71933980), vec2(0.70710678, -0.70710678), vec2(0.71933980, -0.69465837), vec2(0.73135370, -0.68199836), // 672
- vec2(0.74314483, -0.66913061), vec2(0.75470958, -0.65605903), vec2(0.76604444, -0.64278761), vec2(0.77714596, -0.62932039), vec2(0.78801075, -0.61566148), vec2(0.79863551, -0.60181502), // 678
- vec2(0.80901699, -0.58778525), vec2(0.81915204, -0.57357644), vec2(0.82903757, -0.55919290), vec2(0.83867057, -0.54463904), vec2(0.84804810, -0.52991926), vec2(0.85716730, -0.51503807), // 684
- vec2(0.86602540, -0.50000000), vec2(0.87461971, -0.48480962), vec2(0.88294759, -0.46947156), vec2(0.89100652, -0.45399050), vec2(0.89879405, -0.43837115), vec2(0.90630779, -0.42261826), // 690
- vec2(0.91354546, -0.40673664), vec2(0.92050485, -0.39073113), vec2(0.92718385, -0.37460659), vec2(0.93358043, -0.35836795), vec2(0.93969262, -0.34202014), vec2(0.94551858, -0.32556815), // 696
- vec2(0.95105652, -0.30901699), vec2(0.95630476, -0.29237170), vec2(0.96126170, -0.27563736), vec2(0.96592583, -0.25881905), vec2(0.97029573, -0.24192190), vec2(0.97437006, -0.22495105), // 702
- vec2(0.97814760, -0.20791169), vec2(0.98162718, -0.19080900), vec2(0.98480775, -0.17364818), vec2(0.98768834, -0.15643447), vec2(0.99026807, -0.13917310), vec2(0.99254615, -0.12186934), // 708
- vec2(0.99452190, -0.10452846), vec2(0.99619470, -0.08715574), vec2(0.99756405, -0.06975647), vec2(0.99862953, -0.05233596), vec2(0.99939083, -0.03489950), vec2(0.99984770, -0.01745241), // 714
- vec2(1.00000000, 0.00000000) // 720
+ vec2(1.00000000, 0.00000000), vec2(0.99984770, 0.01745241), vec2(0.99939083, 0.03489950), vec2(0.99862953, 0.05233596), vec2(0.99756405, 0.06975647), vec2(0.99619470, 0.08715574), // 0
+ vec2(0.99452190, 0.10452846), vec2(0.99254615, 0.12186934), vec2(0.99026807, 0.13917310), vec2(0.98768834, 0.15643447), vec2(0.98480775, 0.17364818), vec2(0.98162718, 0.19080900), // 6
+ vec2(0.97814760, 0.20791169), vec2(0.97437006, 0.22495105), vec2(0.97029573, 0.24192190), vec2(0.96592583, 0.25881905), vec2(0.96126170, 0.27563736), vec2(0.95630476, 0.29237170), // 12
+ vec2(0.95105652, 0.30901699), vec2(0.94551858, 0.32556815), vec2(0.93969262, 0.34202014), vec2(0.93358043, 0.35836795), vec2(0.92718385, 0.37460659), vec2(0.92050485, 0.39073113), // 18
+ vec2(0.91354546, 0.40673664), vec2(0.90630779, 0.42261826), vec2(0.89879405, 0.43837115), vec2(0.89100652, 0.45399050), vec2(0.88294759, 0.46947156), vec2(0.87461971, 0.48480962), // 24
+ vec2(0.86602540, 0.50000000), vec2(0.85716730, 0.51503807), vec2(0.84804810, 0.52991926), vec2(0.83867057, 0.54463904), vec2(0.82903757, 0.55919290), vec2(0.81915204, 0.57357644), // 30
+ vec2(0.80901699, 0.58778525), vec2(0.79863551, 0.60181502), vec2(0.78801075, 0.61566148), vec2(0.77714596, 0.62932039), vec2(0.76604444, 0.64278761), vec2(0.75470958, 0.65605903), // 36
+ vec2(0.74314483, 0.66913061), vec2(0.73135370, 0.68199836), vec2(0.71933980, 0.69465837), vec2(0.70710678, 0.70710678), vec2(0.69465837, 0.71933980), vec2(0.68199836, 0.73135370), // 42
+ vec2(0.66913061, 0.74314483), vec2(0.65605903, 0.75470958), vec2(0.64278761, 0.76604444), vec2(0.62932039, 0.77714596), vec2(0.61566148, 0.78801075), vec2(0.60181502, 0.79863551), // 48
+ vec2(0.58778525, 0.80901699), vec2(0.57357644, 0.81915204), vec2(0.55919290, 0.82903757), vec2(0.54463904, 0.83867057), vec2(0.52991926, 0.84804810), vec2(0.51503807, 0.85716730), // 54
+ vec2(0.50000000, 0.86602540), vec2(0.48480962, 0.87461971), vec2(0.46947156, 0.88294759), vec2(0.45399050, 0.89100652), vec2(0.43837115, 0.89879405), vec2(0.42261826, 0.90630779), // 60
+ vec2(0.40673664, 0.91354546), vec2(0.39073113, 0.92050485), vec2(0.37460659, 0.92718385), vec2(0.35836795, 0.93358043), vec2(0.34202014, 0.93969262), vec2(0.32556815, 0.94551858), // 66
+ vec2(0.30901699, 0.95105652), vec2(0.29237170, 0.95630476), vec2(0.27563736, 0.96126170), vec2(0.25881905, 0.96592583), vec2(0.24192190, 0.97029573), vec2(0.22495105, 0.97437006), // 72
+ vec2(0.20791169, 0.97814760), vec2(0.19080900, 0.98162718), vec2(0.17364818, 0.98480775), vec2(0.15643447, 0.98768834), vec2(0.13917310, 0.99026807), vec2(0.12186934, 0.99254615), // 78
+ vec2(0.10452846, 0.99452190), vec2(0.08715574, 0.99619470), vec2(0.06975647, 0.99756405), vec2(0.05233596, 0.99862953), vec2(0.03489950, 0.99939083), vec2(0.01745241, 0.99984770), // 84
+ vec2(0.00000000, 1.00000000), vec2(-0.01745241, 0.99984770), vec2(-0.03489950, 0.99939083), vec2(-0.05233596, 0.99862953), vec2(-0.06975647, 0.99756405), vec2(-0.08715574, 0.99619470), // 90
+ vec2(-0.10452846, 0.99452190), vec2(-0.12186934, 0.99254615), vec2(-0.13917310, 0.99026807), vec2(-0.15643447, 0.98768834), vec2(-0.17364818, 0.98480775), vec2(-0.19080900, 0.98162718), // 96
+ vec2(-0.20791169, 0.97814760), vec2(-0.22495105, 0.97437006), vec2(-0.24192190, 0.97029573), vec2(-0.25881905, 0.96592583), vec2(-0.27563736, 0.96126170), vec2(-0.29237170, 0.95630476), // 102
+ vec2(-0.30901699, 0.95105652), vec2(-0.32556815, 0.94551858), vec2(-0.34202014, 0.93969262), vec2(-0.35836795, 0.93358043), vec2(-0.37460659, 0.92718385), vec2(-0.39073113, 0.92050485), // 108
+ vec2(-0.40673664, 0.91354546), vec2(-0.42261826, 0.90630779), vec2(-0.43837115, 0.89879405), vec2(-0.45399050, 0.89100652), vec2(-0.46947156, 0.88294759), vec2(-0.48480962, 0.87461971), // 114
+ vec2(-0.50000000, 0.86602540), vec2(-0.51503807, 0.85716730), vec2(-0.52991926, 0.84804810), vec2(-0.54463904, 0.83867057), vec2(-0.55919290, 0.82903757), vec2(-0.57357644, 0.81915204), // 120
+ vec2(-0.58778525, 0.80901699), vec2(-0.60181502, 0.79863551), vec2(-0.61566148, 0.78801075), vec2(-0.62932039, 0.77714596), vec2(-0.64278761, 0.76604444), vec2(-0.65605903, 0.75470958), // 126
+ vec2(-0.66913061, 0.74314483), vec2(-0.68199836, 0.73135370), vec2(-0.69465837, 0.71933980), vec2(-0.70710678, 0.70710678), vec2(-0.71933980, 0.69465837), vec2(-0.73135370, 0.68199836), // 132
+ vec2(-0.74314483, 0.66913061), vec2(-0.75470958, 0.65605903), vec2(-0.76604444, 0.64278761), vec2(-0.77714596, 0.62932039), vec2(-0.78801075, 0.61566148), vec2(-0.79863551, 0.60181502), // 138
+ vec2(-0.80901699, 0.58778525), vec2(-0.81915204, 0.57357644), vec2(-0.82903757, 0.55919290), vec2(-0.83867057, 0.54463904), vec2(-0.84804810, 0.52991926), vec2(-0.85716730, 0.51503807), // 144
+ vec2(-0.86602540, 0.50000000), vec2(-0.87461971, 0.48480962), vec2(-0.88294759, 0.46947156), vec2(-0.89100652, 0.45399050), vec2(-0.89879405, 0.43837115), vec2(-0.90630779, 0.42261826), // 150
+ vec2(-0.91354546, 0.40673664), vec2(-0.92050485, 0.39073113), vec2(-0.92718385, 0.37460659), vec2(-0.93358043, 0.35836795), vec2(-0.93969262, 0.34202014), vec2(-0.94551858, 0.32556815), // 156
+ vec2(-0.95105652, 0.30901699), vec2(-0.95630476, 0.29237170), vec2(-0.96126170, 0.27563736), vec2(-0.96592583, 0.25881905), vec2(-0.97029573, 0.24192190), vec2(-0.97437006, 0.22495105), // 162
+ vec2(-0.97814760, 0.20791169), vec2(-0.98162718, 0.19080900), vec2(-0.98480775, 0.17364818), vec2(-0.98768834, 0.15643447), vec2(-0.99026807, 0.13917310), vec2(-0.99254615, 0.12186934), // 168
+ vec2(-0.99452190, 0.10452846), vec2(-0.99619470, 0.08715574), vec2(-0.99756405, 0.06975647), vec2(-0.99862953, 0.05233596), vec2(-0.99939083, 0.03489950), vec2(-0.99984770, 0.01745241), // 174
+ vec2(-1.00000000, 0.00000000), vec2(-0.99984770, -0.01745241), vec2(-0.99939083, -0.03489950), vec2(-0.99862953, -0.05233596), vec2(-0.99756405, -0.06975647), vec2(-0.99619470, -0.08715574), // 180
+ vec2(-0.99452190, -0.10452846), vec2(-0.99254615, -0.12186934), vec2(-0.99026807, -0.13917310), vec2(-0.98768834, -0.15643447), vec2(-0.98480775, -0.17364818), vec2(-0.98162718, -0.19080900), // 186
+ vec2(-0.97814760, -0.20791169), vec2(-0.97437006, -0.22495105), vec2(-0.97029573, -0.24192190), vec2(-0.96592583, -0.25881905), vec2(-0.96126170, -0.27563736), vec2(-0.95630476, -0.29237170), // 192
+ vec2(-0.95105652, -0.30901699), vec2(-0.94551858, -0.32556815), vec2(-0.93969262, -0.34202014), vec2(-0.93358043, -0.35836795), vec2(-0.92718385, -0.37460659), vec2(-0.92050485, -0.39073113), // 198
+ vec2(-0.91354546, -0.40673664), vec2(-0.90630779, -0.42261826), vec2(-0.89879405, -0.43837115), vec2(-0.89100652, -0.45399050), vec2(-0.88294759, -0.46947156), vec2(-0.87461971, -0.48480962), // 204
+ vec2(-0.86602540, -0.50000000), vec2(-0.85716730, -0.51503807), vec2(-0.84804810, -0.52991926), vec2(-0.83867057, -0.54463904), vec2(-0.82903757, -0.55919290), vec2(-0.81915204, -0.57357644), // 210
+ vec2(-0.80901699, -0.58778525), vec2(-0.79863551, -0.60181502), vec2(-0.78801075, -0.61566148), vec2(-0.77714596, -0.62932039), vec2(-0.76604444, -0.64278761), vec2(-0.75470958, -0.65605903), // 216
+ vec2(-0.74314483, -0.66913061), vec2(-0.73135370, -0.68199836), vec2(-0.71933980, -0.69465837), vec2(-0.70710678, -0.70710678), vec2(-0.69465837, -0.71933980), vec2(-0.68199836, -0.73135370), // 222
+ vec2(-0.66913061, -0.74314483), vec2(-0.65605903, -0.75470958), vec2(-0.64278761, -0.76604444), vec2(-0.62932039, -0.77714596), vec2(-0.61566148, -0.78801075), vec2(-0.60181502, -0.79863551), // 228
+ vec2(-0.58778525, -0.80901699), vec2(-0.57357644, -0.81915204), vec2(-0.55919290, -0.82903757), vec2(-0.54463904, -0.83867057), vec2(-0.52991926, -0.84804810), vec2(-0.51503807, -0.85716730), // 234
+ vec2(-0.50000000, -0.86602540), vec2(-0.48480962, -0.87461971), vec2(-0.46947156, -0.88294759), vec2(-0.45399050, -0.89100652), vec2(-0.43837115, -0.89879405), vec2(-0.42261826, -0.90630779), // 240
+ vec2(-0.40673664, -0.91354546), vec2(-0.39073113, -0.92050485), vec2(-0.37460659, -0.92718385), vec2(-0.35836795, -0.93358043), vec2(-0.34202014, -0.93969262), vec2(-0.32556815, -0.94551858), // 246
+ vec2(-0.30901699, -0.95105652), vec2(-0.29237170, -0.95630476), vec2(-0.27563736, -0.96126170), vec2(-0.25881905, -0.96592583), vec2(-0.24192190, -0.97029573), vec2(-0.22495105, -0.97437006), // 252
+ vec2(-0.20791169, -0.97814760), vec2(-0.19080900, -0.98162718), vec2(-0.17364818, -0.98480775), vec2(-0.15643447, -0.98768834), vec2(-0.13917310, -0.99026807), vec2(-0.12186934, -0.99254615), // 258
+ vec2(-0.10452846, -0.99452190), vec2(-0.08715574, -0.99619470), vec2(-0.06975647, -0.99756405), vec2(-0.05233596, -0.99862953), vec2(-0.03489950, -0.99939083), vec2(-0.01745241, -0.99984770), // 264
+ vec2(-0.00000000, -1.00000000), vec2(0.01745241, -0.99984770), vec2(0.03489950, -0.99939083), vec2(0.05233596, -0.99862953), vec2(0.06975647, -0.99756405), vec2(0.08715574, -0.99619470), // 270
+ vec2(0.10452846, -0.99452190), vec2(0.12186934, -0.99254615), vec2(0.13917310, -0.99026807), vec2(0.15643447, -0.98768834), vec2(0.17364818, -0.98480775), vec2(0.19080900, -0.98162718), // 276
+ vec2(0.20791169, -0.97814760), vec2(0.22495105, -0.97437006), vec2(0.24192190, -0.97029573), vec2(0.25881905, -0.96592583), vec2(0.27563736, -0.96126170), vec2(0.29237170, -0.95630476), // 282
+ vec2(0.30901699, -0.95105652), vec2(0.32556815, -0.94551858), vec2(0.34202014, -0.93969262), vec2(0.35836795, -0.93358043), vec2(0.37460659, -0.92718385), vec2(0.39073113, -0.92050485), // 288
+ vec2(0.40673664, -0.91354546), vec2(0.42261826, -0.90630779), vec2(0.43837115, -0.89879405), vec2(0.45399050, -0.89100652), vec2(0.46947156, -0.88294759), vec2(0.48480962, -0.87461971), // 294
+ vec2(0.50000000, -0.86602540), vec2(0.51503807, -0.85716730), vec2(0.52991926, -0.84804810), vec2(0.54463904, -0.83867057), vec2(0.55919290, -0.82903757), vec2(0.57357644, -0.81915204), // 300
+ vec2(0.58778525, -0.80901699), vec2(0.60181502, -0.79863551), vec2(0.61566148, -0.78801075), vec2(0.62932039, -0.77714596), vec2(0.64278761, -0.76604444), vec2(0.65605903, -0.75470958), // 306
+ vec2(0.66913061, -0.74314483), vec2(0.68199836, -0.73135370), vec2(0.69465837, -0.71933980), vec2(0.70710678, -0.70710678), vec2(0.71933980, -0.69465837), vec2(0.73135370, -0.68199836), // 312
+ vec2(0.74314483, -0.66913061), vec2(0.75470958, -0.65605903), vec2(0.76604444, -0.64278761), vec2(0.77714596, -0.62932039), vec2(0.78801075, -0.61566148), vec2(0.79863551, -0.60181502), // 318
+ vec2(0.80901699, -0.58778525), vec2(0.81915204, -0.57357644), vec2(0.82903757, -0.55919290), vec2(0.83867057, -0.54463904), vec2(0.84804810, -0.52991926), vec2(0.85716730, -0.51503807), // 324
+ vec2(0.86602540, -0.50000000), vec2(0.87461971, -0.48480962), vec2(0.88294759, -0.46947156), vec2(0.89100652, -0.45399050), vec2(0.89879405, -0.43837115), vec2(0.90630779, -0.42261826), // 330
+ vec2(0.91354546, -0.40673664), vec2(0.92050485, -0.39073113), vec2(0.92718385, -0.37460659), vec2(0.93358043, -0.35836795), vec2(0.93969262, -0.34202014), vec2(0.94551858, -0.32556815), // 336
+ vec2(0.95105652, -0.30901699), vec2(0.95630476, -0.29237170), vec2(0.96126170, -0.27563736), vec2(0.96592583, -0.25881905), vec2(0.97029573, -0.24192190), vec2(0.97437006, -0.22495105), // 342
+ vec2(0.97814760, -0.20791169), vec2(0.98162718, -0.19080900), vec2(0.98480775, -0.17364818), vec2(0.98768834, -0.15643447), vec2(0.99026807, -0.13917310), vec2(0.99254615, -0.12186934), // 348
+ vec2(0.99452190, -0.10452846), vec2(0.99619470, -0.08715574), vec2(0.99756405, -0.06975647), vec2(0.99862953, -0.05233596), vec2(0.99939083, -0.03489950), vec2(0.99984770, -0.01745241), // 354
+ vec2(1.00000000, 0.00000000), vec2(0.99984770, 0.01745241), vec2(0.99939083, 0.03489950), vec2(0.99862953, 0.05233596), vec2(0.99756405, 0.06975647), vec2(0.99619470, 0.08715574), // 360
+ vec2(0.99452190, 0.10452846), vec2(0.99254615, 0.12186934), vec2(0.99026807, 0.13917310), vec2(0.98768834, 0.15643447), vec2(0.98480775, 0.17364818), vec2(0.98162718, 0.19080900), // 366
+ vec2(0.97814760, 0.20791169), vec2(0.97437006, 0.22495105), vec2(0.97029573, 0.24192190), vec2(0.96592583, 0.25881905), vec2(0.96126170, 0.27563736), vec2(0.95630476, 0.29237170), // 372
+ vec2(0.95105652, 0.30901699), vec2(0.94551858, 0.32556815), vec2(0.93969262, 0.34202014), vec2(0.93358043, 0.35836795), vec2(0.92718385, 0.37460659), vec2(0.92050485, 0.39073113), // 378
+ vec2(0.91354546, 0.40673664), vec2(0.90630779, 0.42261826), vec2(0.89879405, 0.43837115), vec2(0.89100652, 0.45399050), vec2(0.88294759, 0.46947156), vec2(0.87461971, 0.48480962), // 384
+ vec2(0.86602540, 0.50000000), vec2(0.85716730, 0.51503807), vec2(0.84804810, 0.52991926), vec2(0.83867057, 0.54463904), vec2(0.82903757, 0.55919290), vec2(0.81915204, 0.57357644), // 390
+ vec2(0.80901699, 0.58778525), vec2(0.79863551, 0.60181502), vec2(0.78801075, 0.61566148), vec2(0.77714596, 0.62932039), vec2(0.76604444, 0.64278761), vec2(0.75470958, 0.65605903), // 396
+ vec2(0.74314483, 0.66913061), vec2(0.73135370, 0.68199836), vec2(0.71933980, 0.69465837), vec2(0.70710678, 0.70710678), vec2(0.69465837, 0.71933980), vec2(0.68199836, 0.73135370), // 402
+ vec2(0.66913061, 0.74314483), vec2(0.65605903, 0.75470958), vec2(0.64278761, 0.76604444), vec2(0.62932039, 0.77714596), vec2(0.61566148, 0.78801075), vec2(0.60181502, 0.79863551), // 408
+ vec2(0.58778525, 0.80901699), vec2(0.57357644, 0.81915204), vec2(0.55919290, 0.82903757), vec2(0.54463904, 0.83867057), vec2(0.52991926, 0.84804810), vec2(0.51503807, 0.85716730), // 414
+ vec2(0.50000000, 0.86602540), vec2(0.48480962, 0.87461971), vec2(0.46947156, 0.88294759), vec2(0.45399050, 0.89100652), vec2(0.43837115, 0.89879405), vec2(0.42261826, 0.90630779), // 420
+ vec2(0.40673664, 0.91354546), vec2(0.39073113, 0.92050485), vec2(0.37460659, 0.92718385), vec2(0.35836795, 0.93358043), vec2(0.34202014, 0.93969262), vec2(0.32556815, 0.94551858), // 426
+ vec2(0.30901699, 0.95105652), vec2(0.29237170, 0.95630476), vec2(0.27563736, 0.96126170), vec2(0.25881905, 0.96592583), vec2(0.24192190, 0.97029573), vec2(0.22495105, 0.97437006), // 432
+ vec2(0.20791169, 0.97814760), vec2(0.19080900, 0.98162718), vec2(0.17364818, 0.98480775), vec2(0.15643447, 0.98768834), vec2(0.13917310, 0.99026807), vec2(0.12186934, 0.99254615), // 438
+ vec2(0.10452846, 0.99452190), vec2(0.08715574, 0.99619470), vec2(0.06975647, 0.99756405), vec2(0.05233596, 0.99862953), vec2(0.03489950, 0.99939083), vec2(0.01745241, 0.99984770), // 444
+ vec2(0.00000000, 1.00000000), vec2(-0.01745241, 0.99984770), vec2(-0.03489950, 0.99939083), vec2(-0.05233596, 0.99862953), vec2(-0.06975647, 0.99756405), vec2(-0.08715574, 0.99619470), // 450
+ vec2(-0.10452846, 0.99452190), vec2(-0.12186934, 0.99254615), vec2(-0.13917310, 0.99026807), vec2(-0.15643447, 0.98768834), vec2(-0.17364818, 0.98480775), vec2(-0.19080900, 0.98162718), // 456
+ vec2(-0.20791169, 0.97814760), vec2(-0.22495105, 0.97437006), vec2(-0.24192190, 0.97029573), vec2(-0.25881905, 0.96592583), vec2(-0.27563736, 0.96126170), vec2(-0.29237170, 0.95630476), // 462
+ vec2(-0.30901699, 0.95105652), vec2(-0.32556815, 0.94551858), vec2(-0.34202014, 0.93969262), vec2(-0.35836795, 0.93358043), vec2(-0.37460659, 0.92718385), vec2(-0.39073113, 0.92050485), // 468
+ vec2(-0.40673664, 0.91354546), vec2(-0.42261826, 0.90630779), vec2(-0.43837115, 0.89879405), vec2(-0.45399050, 0.89100652), vec2(-0.46947156, 0.88294759), vec2(-0.48480962, 0.87461971), // 474
+ vec2(-0.50000000, 0.86602540), vec2(-0.51503807, 0.85716730), vec2(-0.52991926, 0.84804810), vec2(-0.54463904, 0.83867057), vec2(-0.55919290, 0.82903757), vec2(-0.57357644, 0.81915204), // 480
+ vec2(-0.58778525, 0.80901699), vec2(-0.60181502, 0.79863551), vec2(-0.61566148, 0.78801075), vec2(-0.62932039, 0.77714596), vec2(-0.64278761, 0.76604444), vec2(-0.65605903, 0.75470958), // 486
+ vec2(-0.66913061, 0.74314483), vec2(-0.68199836, 0.73135370), vec2(-0.69465837, 0.71933980), vec2(-0.70710678, 0.70710678), vec2(-0.71933980, 0.69465837), vec2(-0.73135370, 0.68199836), // 492
+ vec2(-0.74314483, 0.66913061), vec2(-0.75470958, 0.65605903), vec2(-0.76604444, 0.64278761), vec2(-0.77714596, 0.62932039), vec2(-0.78801075, 0.61566148), vec2(-0.79863551, 0.60181502), // 498
+ vec2(-0.80901699, 0.58778525), vec2(-0.81915204, 0.57357644), vec2(-0.82903757, 0.55919290), vec2(-0.83867057, 0.54463904), vec2(-0.84804810, 0.52991926), vec2(-0.85716730, 0.51503807), // 504
+ vec2(-0.86602540, 0.50000000), vec2(-0.87461971, 0.48480962), vec2(-0.88294759, 0.46947156), vec2(-0.89100652, 0.45399050), vec2(-0.89879405, 0.43837115), vec2(-0.90630779, 0.42261826), // 510
+ vec2(-0.91354546, 0.40673664), vec2(-0.92050485, 0.39073113), vec2(-0.92718385, 0.37460659), vec2(-0.93358043, 0.35836795), vec2(-0.93969262, 0.34202014), vec2(-0.94551858, 0.32556815), // 516
+ vec2(-0.95105652, 0.30901699), vec2(-0.95630476, 0.29237170), vec2(-0.96126170, 0.27563736), vec2(-0.96592583, 0.25881905), vec2(-0.97029573, 0.24192190), vec2(-0.97437006, 0.22495105), // 522
+ vec2(-0.97814760, 0.20791169), vec2(-0.98162718, 0.19080900), vec2(-0.98480775, 0.17364818), vec2(-0.98768834, 0.15643447), vec2(-0.99026807, 0.13917310), vec2(-0.99254615, 0.12186934), // 528
+ vec2(-0.99452190, 0.10452846), vec2(-0.99619470, 0.08715574), vec2(-0.99756405, 0.06975647), vec2(-0.99862953, 0.05233596), vec2(-0.99939083, 0.03489950), vec2(-0.99984770, 0.01745241), // 534
+ vec2(-1.00000000, 0.00000000), vec2(-0.99984770, -0.01745241), vec2(-0.99939083, -0.03489950), vec2(-0.99862953, -0.05233596), vec2(-0.99756405, -0.06975647), vec2(-0.99619470, -0.08715574), // 540
+ vec2(-0.99452190, -0.10452846), vec2(-0.99254615, -0.12186934), vec2(-0.99026807, -0.13917310), vec2(-0.98768834, -0.15643447), vec2(-0.98480775, -0.17364818), vec2(-0.98162718, -0.19080900), // 546
+ vec2(-0.97814760, -0.20791169), vec2(-0.97437006, -0.22495105), vec2(-0.97029573, -0.24192190), vec2(-0.96592583, -0.25881905), vec2(-0.96126170, -0.27563736), vec2(-0.95630476, -0.29237170), // 552
+ vec2(-0.95105652, -0.30901699), vec2(-0.94551858, -0.32556815), vec2(-0.93969262, -0.34202014), vec2(-0.93358043, -0.35836795), vec2(-0.92718385, -0.37460659), vec2(-0.92050485, -0.39073113), // 558
+ vec2(-0.91354546, -0.40673664), vec2(-0.90630779, -0.42261826), vec2(-0.89879405, -0.43837115), vec2(-0.89100652, -0.45399050), vec2(-0.88294759, -0.46947156), vec2(-0.87461971, -0.48480962), // 564
+ vec2(-0.86602540, -0.50000000), vec2(-0.85716730, -0.51503807), vec2(-0.84804810, -0.52991926), vec2(-0.83867057, -0.54463904), vec2(-0.82903757, -0.55919290), vec2(-0.81915204, -0.57357644), // 570
+ vec2(-0.80901699, -0.58778525), vec2(-0.79863551, -0.60181502), vec2(-0.78801075, -0.61566148), vec2(-0.77714596, -0.62932039), vec2(-0.76604444, -0.64278761), vec2(-0.75470958, -0.65605903), // 576
+ vec2(-0.74314483, -0.66913061), vec2(-0.73135370, -0.68199836), vec2(-0.71933980, -0.69465837), vec2(-0.70710678, -0.70710678), vec2(-0.69465837, -0.71933980), vec2(-0.68199836, -0.73135370), // 582
+ vec2(-0.66913061, -0.74314483), vec2(-0.65605903, -0.75470958), vec2(-0.64278761, -0.76604444), vec2(-0.62932039, -0.77714596), vec2(-0.61566148, -0.78801075), vec2(-0.60181502, -0.79863551), // 588
+ vec2(-0.58778525, -0.80901699), vec2(-0.57357644, -0.81915204), vec2(-0.55919290, -0.82903757), vec2(-0.54463904, -0.83867057), vec2(-0.52991926, -0.84804810), vec2(-0.51503807, -0.85716730), // 594
+ vec2(-0.50000000, -0.86602540), vec2(-0.48480962, -0.87461971), vec2(-0.46947156, -0.88294759), vec2(-0.45399050, -0.89100652), vec2(-0.43837115, -0.89879405), vec2(-0.42261826, -0.90630779), // 600
+ vec2(-0.40673664, -0.91354546), vec2(-0.39073113, -0.92050485), vec2(-0.37460659, -0.92718385), vec2(-0.35836795, -0.93358043), vec2(-0.34202014, -0.93969262), vec2(-0.32556815, -0.94551858), // 606
+ vec2(-0.30901699, -0.95105652), vec2(-0.29237170, -0.95630476), vec2(-0.27563736, -0.96126170), vec2(-0.25881905, -0.96592583), vec2(-0.24192190, -0.97029573), vec2(-0.22495105, -0.97437006), // 612
+ vec2(-0.20791169, -0.97814760), vec2(-0.19080900, -0.98162718), vec2(-0.17364818, -0.98480775), vec2(-0.15643447, -0.98768834), vec2(-0.13917310, -0.99026807), vec2(-0.12186934, -0.99254615), // 618
+ vec2(-0.10452846, -0.99452190), vec2(-0.08715574, -0.99619470), vec2(-0.06975647, -0.99756405), vec2(-0.05233596, -0.99862953), vec2(-0.03489950, -0.99939083), vec2(-0.01745241, -0.99984770), // 624
+ vec2(-0.00000000, -1.00000000), vec2(0.01745241, -0.99984770), vec2(0.03489950, -0.99939083), vec2(0.05233596, -0.99862953), vec2(0.06975647, -0.99756405), vec2(0.08715574, -0.99619470), // 630
+ vec2(0.10452846, -0.99452190), vec2(0.12186934, -0.99254615), vec2(0.13917310, -0.99026807), vec2(0.15643447, -0.98768834), vec2(0.17364818, -0.98480775), vec2(0.19080900, -0.98162718), // 636
+ vec2(0.20791169, -0.97814760), vec2(0.22495105, -0.97437006), vec2(0.24192190, -0.97029573), vec2(0.25881905, -0.96592583), vec2(0.27563736, -0.96126170), vec2(0.29237170, -0.95630476), // 642
+ vec2(0.30901699, -0.95105652), vec2(0.32556815, -0.94551858), vec2(0.34202014, -0.93969262), vec2(0.35836795, -0.93358043), vec2(0.37460659, -0.92718385), vec2(0.39073113, -0.92050485), // 648
+ vec2(0.40673664, -0.91354546), vec2(0.42261826, -0.90630779), vec2(0.43837115, -0.89879405), vec2(0.45399050, -0.89100652), vec2(0.46947156, -0.88294759), vec2(0.48480962, -0.87461971), // 654
+ vec2(0.50000000, -0.86602540), vec2(0.51503807, -0.85716730), vec2(0.52991926, -0.84804810), vec2(0.54463904, -0.83867057), vec2(0.55919290, -0.82903757), vec2(0.57357644, -0.81915204), // 660
+ vec2(0.58778525, -0.80901699), vec2(0.60181502, -0.79863551), vec2(0.61566148, -0.78801075), vec2(0.62932039, -0.77714596), vec2(0.64278761, -0.76604444), vec2(0.65605903, -0.75470958), // 666
+ vec2(0.66913061, -0.74314483), vec2(0.68199836, -0.73135370), vec2(0.69465837, -0.71933980), vec2(0.70710678, -0.70710678), vec2(0.71933980, -0.69465837), vec2(0.73135370, -0.68199836), // 672
+ vec2(0.74314483, -0.66913061), vec2(0.75470958, -0.65605903), vec2(0.76604444, -0.64278761), vec2(0.77714596, -0.62932039), vec2(0.78801075, -0.61566148), vec2(0.79863551, -0.60181502), // 678
+ vec2(0.80901699, -0.58778525), vec2(0.81915204, -0.57357644), vec2(0.82903757, -0.55919290), vec2(0.83867057, -0.54463904), vec2(0.84804810, -0.52991926), vec2(0.85716730, -0.51503807), // 684
+ vec2(0.86602540, -0.50000000), vec2(0.87461971, -0.48480962), vec2(0.88294759, -0.46947156), vec2(0.89100652, -0.45399050), vec2(0.89879405, -0.43837115), vec2(0.90630779, -0.42261826), // 690
+ vec2(0.91354546, -0.40673664), vec2(0.92050485, -0.39073113), vec2(0.92718385, -0.37460659), vec2(0.93358043, -0.35836795), vec2(0.93969262, -0.34202014), vec2(0.94551858, -0.32556815), // 696
+ vec2(0.95105652, -0.30901699), vec2(0.95630476, -0.29237170), vec2(0.96126170, -0.27563736), vec2(0.96592583, -0.25881905), vec2(0.97029573, -0.24192190), vec2(0.97437006, -0.22495105), // 702
+ vec2(0.97814760, -0.20791169), vec2(0.98162718, -0.19080900), vec2(0.98480775, -0.17364818), vec2(0.98768834, -0.15643447), vec2(0.99026807, -0.13917310), vec2(0.99254615, -0.12186934), // 708
+ vec2(0.99452190, -0.10452846), vec2(0.99619470, -0.08715574), vec2(0.99756405, -0.06975647), vec2(0.99862953, -0.05233596), vec2(0.99939083, -0.03489950), vec2(0.99984770, -0.01745241), // 714
+ vec2(1.00000000, 0.00000000) // 720
};
diff --git a/src/shared/geom.h b/src/shared/geom.h
index 3adccc6..e01acc2 100644
--- a/src/shared/geom.h
+++ b/src/shared/geom.h
@@ -3,327 +3,327 @@ struct vec4;
struct vec2
{
- union
- {
- struct { float x, y; };
- float v[2];
- };
-
- vec2() {}
- vec2(float x, float y) : x(x), y(y) {}
- explicit vec2(const vec &v);
- explicit vec2(const vec4 &v);
-
- float &operator[](int i) { return v[i]; }
- float operator[](int i) const { return v[i]; }
-
- bool operator==(const vec2 &o) const { return x == o.x && y == o.y; }
- bool operator!=(const vec2 &o) const { return x != o.x || y != o.y; }
-
- bool iszero() const { return x==0 && y==0; }
- float dot(const vec2 &o) const { return x*o.x + y*o.y; }
- float squaredlen() const { return dot(*this); }
- float magnitude() const { return sqrtf(squaredlen()); }
- vec2 &normalize() { mul(1/magnitude()); return *this; }
- vec2 &safenormalize() { float m = magnitude(); if(m) mul(1/m); return *this; }
- float cross(const vec2 &o) const { return x*o.y - y*o.x; }
-
- vec2 &mul(float f) { x *= f; y *= f; return *this; }
- vec2 &mul(const vec2 &o) { x *= o.x; y *= o.y; return *this; }
- vec2 &square() { mul(*this); return *this; }
- vec2 &div(float f) { x /= f; y /= f; return *this; }
- vec2 &div(const vec2 &o) { x /= o.x; y /= o.y; return *this; }
- vec2 &recip() { x = 1/x; y = 1/y; return *this; }
- vec2 &add(float f) { x += f; y += f; return *this; }
- vec2 &add(const vec2 &o) { x += o.x; y += o.y; return *this; }
- vec2 &sub(float f) { x -= f; y -= f; return *this; }
- vec2 &sub(const vec2 &o) { x -= o.x; y -= o.y; return *this; }
- vec2 &neg() { x = -x; y = -y; return *this; }
- vec2 &min(const vec2 &o) { x = ::min(x, o.x); y = ::min(y, o.y); return *this; }
- vec2 &max(const vec2 &o) { x = ::max(x, o.x); y = ::max(y, o.y); return *this; }
- vec2 &min(float f) { x = ::min(x, f); y = ::min(y, f); return *this; }
- vec2 &max(float f) { x = ::max(x, f); y = ::max(y, f); return *this; }
- vec2 &abs() { x = fabs(x); y = fabs(y); return *this; }
- vec2 &clamp(float l, float h) { x = ::clamp(x, l, h); y = ::clamp(y, l, h); return *this; }
- vec2 &reflect(const vec2 &n) { float k = 2*dot(n); x -= k*n.x; y -= k*n.y; return *this; }
- vec2 &lerp(const vec2 &b, float t) { x += (b.x-x)*t; y += (b.y-y)*t; return *this; }
- vec2 &lerp(const vec2 &a, const vec2 &b, float t) { x = a.x + (b.x-a.x)*t; y = a.y + (b.y-a.y)*t; return *this; }
- template<class B> vec2 &madd(const vec2 &a, const B &b) { return add(vec2(a).mul(b)); }
- template<class B> vec2 &msub(const vec2 &a, const B &b) { return sub(vec2(a).mul(b)); }
+ union
+ {
+ struct { float x, y; };
+ float v[2];
+ };
+
+ vec2() {}
+ vec2(float x, float y) : x(x), y(y) {}
+ explicit vec2(const vec &v);
+ explicit vec2(const vec4 &v);
+
+ float &operator[](int i) { return v[i]; }
+ float operator[](int i) const { return v[i]; }
+
+ bool operator==(const vec2 &o) const { return x == o.x && y == o.y; }
+ bool operator!=(const vec2 &o) const { return x != o.x || y != o.y; }
+
+ bool iszero() const { return x==0 && y==0; }
+ float dot(const vec2 &o) const { return x*o.x + y*o.y; }
+ float squaredlen() const { return dot(*this); }
+ float magnitude() const { return sqrtf(squaredlen()); }
+ vec2 &normalize() { mul(1/magnitude()); return *this; }
+ vec2 &safenormalize() { float m = magnitude(); if(m) mul(1/m); return *this; }
+ float cross(const vec2 &o) const { return x*o.y - y*o.x; }
+
+ vec2 &mul(float f) { x *= f; y *= f; return *this; }
+ vec2 &mul(const vec2 &o) { x *= o.x; y *= o.y; return *this; }
+ vec2 &square() { mul(*this); return *this; }
+ vec2 &div(float f) { x /= f; y /= f; return *this; }
+ vec2 &div(const vec2 &o) { x /= o.x; y /= o.y; return *this; }
+ vec2 &recip() { x = 1/x; y = 1/y; return *this; }
+ vec2 &add(float f) { x += f; y += f; return *this; }
+ vec2 &add(const vec2 &o) { x += o.x; y += o.y; return *this; }
+ vec2 &sub(float f) { x -= f; y -= f; return *this; }
+ vec2 &sub(const vec2 &o) { x -= o.x; y -= o.y; return *this; }
+ vec2 &neg() { x = -x; y = -y; return *this; }
+ vec2 &min(const vec2 &o) { x = ::min(x, o.x); y = ::min(y, o.y); return *this; }
+ vec2 &max(const vec2 &o) { x = ::max(x, o.x); y = ::max(y, o.y); return *this; }
+ vec2 &min(float f) { x = ::min(x, f); y = ::min(y, f); return *this; }
+ vec2 &max(float f) { x = ::max(x, f); y = ::max(y, f); return *this; }
+ vec2 &abs() { x = fabs(x); y = fabs(y); return *this; }
+ vec2 &clamp(float l, float h) { x = ::clamp(x, l, h); y = ::clamp(y, l, h); return *this; }
+ vec2 &reflect(const vec2 &n) { float k = 2*dot(n); x -= k*n.x; y -= k*n.y; return *this; }
+ vec2 &lerp(const vec2 &b, float t) { x += (b.x-x)*t; y += (b.y-y)*t; return *this; }
+ vec2 &lerp(const vec2 &a, const vec2 &b, float t) { x = a.x + (b.x-a.x)*t; y = a.y + (b.y-a.y)*t; return *this; }
+ template<class B> vec2 &madd(const vec2 &a, const B &b) { return add(vec2(a).mul(b)); }
+ template<class B> vec2 &msub(const vec2 &a, const B &b) { return sub(vec2(a).mul(b)); }
};
static inline bool htcmp(const vec2 &x, const vec2 &y)
{
- return x == y;
+ return x == y;
}
static inline uint hthash(const vec2 &k)
{
- union { uint i; float f; } x, y;
- x.f = k.x; y.f = k.y;
- uint v = x.i^y.i;
- return v + (v>>12);
+ union { uint i; float f; } x, y;
+ x.f = k.x; y.f = k.y;
+ uint v = x.i^y.i;
+ return v + (v>>12);
}
struct ivec;
struct vec
{
- union
- {
- struct { float x, y, z; };
- struct { float r, g, b; };
- float v[3];
- };
-
- vec() {}
- explicit vec(int a) : x(a), y(a), z(a) {}
- explicit vec(float a) : x(a), y(a), z(a) {}
- vec(float a, float b, float c) : x(a), y(b), z(c) {}
- explicit vec(int v[3]) : x(v[0]), y(v[1]), z(v[2]) {}
- explicit vec(const float *v) : x(v[0]), y(v[1]), z(v[2]) {}
- explicit vec(const vec2 &v, float z = 0) : x(v.x), y(v.y), z(z) {}
- explicit vec(const vec4 &v);
- explicit vec(const ivec &v);
-
- vec(float yaw, float pitch) : x(-sinf(yaw)*cosf(pitch)), y(cosf(yaw)*cosf(pitch)), z(sinf(pitch)) {}
-
- float &operator[](int i) { return v[i]; }
- float operator[](int i) const { return v[i]; }
-
- vec &set(int i, float f) { v[i] = f; return *this; }
-
- bool operator==(const vec &o) const { return x == o.x && y == o.y && z == o.z; }
- bool operator!=(const vec &o) const { return x != o.x || y != o.y || z != o.z; }
-
- bool iszero() const { return x==0 && y==0 && z==0; }
- float squaredlen() const { return x*x + y*y + z*z; }
- template<class T> float dot2(const T &o) const { return x*o.x + y*o.y; }
- float dot(const vec &o) const { return x*o.x + y*o.y + z*o.z; }
- float absdot(const vec &o) const { return fabs(x*o.x) + fabs(y*o.y) + fabs(z*o.z); }
- vec &pow(float f) { x = ::pow(x, f); y = ::pow(y, f); z = ::pow(z, f); return *this; }
- vec &exp() { x = ::exp(x); y = ::exp(y); z = ::exp(z); return *this; }
- vec &exp2() { x = ::exp2(x); y = ::exp2(y); z = ::exp2(z); return *this; }
- vec &sqrt() { x = sqrtf(x); y = sqrtf(y); z = sqrtf(z); return *this; }
- vec &mul(const vec &o) { x *= o.x; y *= o.y; z *= o.z; return *this; }
- vec &mul(float f) { x *= f; y *= f; z *= f; return *this; }
- vec &square() { mul(*this); return *this; }
- vec &div(const vec &o) { x /= o.x; y /= o.y; z /= o.z; return *this; }
- vec &div(float f) { x /= f; y /= f; z /= f; return *this; }
- vec &recip() { x = 1/x; y = 1/y; z = 1/z; return *this; }
- vec &add(const vec &o) { x += o.x; y += o.y; z += o.z; return *this; }
- vec &add(float f) { x += f; y += f; z += f; return *this; }
- vec &add2(float f) { x += f; y += f; return *this; }
- vec &addz(float f) { z += f; return *this; }
- vec &sub(const vec &o) { x -= o.x; y -= o.y; z -= o.z; return *this; }
- vec &sub(float f) { x -= f; y -= f; z -= f; return *this; }
- vec &sub2(float f) { x -= f; y -= f; return *this; }
- vec &subz(float f) { z -= f; return *this; }
- vec &neg2() { x = -x; y = -y; return *this; }
- vec &neg() { x = -x; y = -y; z = -z; return *this; }
- vec &min(const vec &o) { x = ::min(x, o.x); y = ::min(y, o.y); z = ::min(z, o.z); return *this; }
- vec &max(const vec &o) { x = ::max(x, o.x); y = ::max(y, o.y); z = ::max(z, o.z); return *this; }
- vec &min(float f) { x = ::min(x, f); y = ::min(y, f); z = ::min(z, f); return *this; }
- vec &max(float f) { x = ::max(x, f); y = ::max(y, f); z = ::max(z, f); return *this; }
- vec &clamp(float f, float h) { x = ::clamp(x, f, h); y = ::clamp(y, f, h); z = ::clamp(z, f, h); return *this; }
- vec &abs() { x = fabs(x); y = fabs(y); z = fabs(z); return *this; }
- float magnitude2() const { return sqrtf(dot2(*this)); }
- float magnitude() const { return sqrtf(squaredlen()); }
- vec &normalize() { div(magnitude()); return *this; }
- vec &safenormalize() { float m = magnitude(); if(m) div(m); return *this; }
- bool isnormalized() const { float m = squaredlen(); return (m>0.99f && m<1.01f); }
- float squaredist(const vec &e) const { return vec(*this).sub(e).squaredlen(); }
- float dist(const vec &e) const { vec t; return dist(e, t); }
- float dist(const vec &e, vec &t) const { t = *this; t.sub(e); return t.magnitude(); }
- float dist2(const vec &o) const { float dx = x-o.x, dy = y-o.y; return sqrtf(dx*dx + dy*dy); }
- bool reject(const vec &o, float r) { return x>o.x+r || x<o.x-r || y>o.y+r || y<o.y-r; }
- template<class A, class B>
- vec &cross(const A &a, const B &b) { x = a.y*b.z-a.z*b.y; y = a.z*b.x-a.x*b.z; z = a.x*b.y-a.y*b.x; return *this; }
- vec &cross(const vec &o, const vec &a, const vec &b) { return cross(vec(a).sub(o), vec(b).sub(o)); }
- float scalartriple(const vec &a, const vec &b) const { return x*(a.y*b.z-a.z*b.y) + y*(a.z*b.x-a.x*b.z) + z*(a.x*b.y-a.y*b.x); }
- vec &reflectz(float rz) { z = 2*rz - z; return *this; }
- vec &reflect(const vec &n) { float k = 2*dot(n); x -= k*n.x; y -= k*n.y; z -= k*n.z; return *this; }
- vec &project(const vec &n) { float k = dot(n); x -= k*n.x; y -= k*n.y; z -= k*n.z; return *this; }
- vec &projectxydir(const vec &n) { if(n.z) z = -(x*n.x/n.z + y*n.y/n.z); return *this; }
- vec &projectxy(const vec &n)
- {
- float m = squaredlen(), k = dot(n);
- projectxydir(n);
- rescale(sqrtf(::max(m - k*k, 0.0f)));
- return *this;
- }
- vec &projectxy(const vec &n, float threshold)
- {
- float m = squaredlen(), k = ::min(dot(n), threshold);
- projectxydir(n);
- rescale(sqrtf(::max(m - k*k, 0.0f)));
- return *this;
- }
- vec &lerp(const vec &b, float t) { x += (b.x-x)*t; y += (b.y-y)*t; z += (b.z-z)*t; return *this; }
- vec &lerp(const vec &a, const vec &b, float t) { x = a.x + (b.x-a.x)*t; y = a.y + (b.y-a.y)*t; z = a.z + (b.z-a.z)*t; return *this; }
- template<class B> vec &madd(const vec &a, const B &b) { return add(vec(a).mul(b)); }
- template<class B> vec &msub(const vec &a, const B &b) { return sub(vec(a).mul(b)); }
-
- vec &rescale(float k)
- {
- float mag = magnitude();
- if(mag > 1e-6f) mul(k / mag);
- return *this;
- }
-
- vec &rotate_around_z(float c, float s) { float rx = x, ry = y; x = c*rx-s*ry; y = c*ry+s*rx; return *this; }
- vec &rotate_around_x(float c, float s) { float ry = y, rz = z; y = c*ry-s*rz; z = c*rz+s*ry; return *this; }
- vec &rotate_around_y(float c, float s) { float rx = x, rz = z; x = c*rx+s*rz; z = c*rz-s*rx; return *this; }
-
- vec &rotate_around_z(float angle) { return rotate_around_z(cosf(angle), sinf(angle)); }
- vec &rotate_around_x(float angle) { return rotate_around_x(cosf(angle), sinf(angle)); }
- vec &rotate_around_y(float angle) { return rotate_around_y(cosf(angle), sinf(angle)); }
-
- vec &rotate_around_z(const vec2 &sc) { return rotate_around_z(sc.x, sc.y); }
- vec &rotate_around_x(const vec2 &sc) { return rotate_around_x(sc.x, sc.y); }
- vec &rotate_around_y(const vec2 &sc) { return rotate_around_y(sc.x, sc.y); }
-
- vec &rotate(float c, float s, const vec &d)
- {
- *this = vec(x*(d.x*d.x*(1-c)+c) + y*(d.x*d.y*(1-c)-d.z*s) + z*(d.x*d.z*(1-c)+d.y*s),
- x*(d.y*d.x*(1-c)+d.z*s) + y*(d.y*d.y*(1-c)+c) + z*(d.y*d.z*(1-c)-d.x*s),
- x*(d.x*d.z*(1-c)-d.y*s) + y*(d.y*d.z*(1-c)+d.x*s) + z*(d.z*d.z*(1-c)+c));
- return *this;
- }
- vec &rotate(float angle, const vec &d) { return rotate(cosf(angle), sinf(angle), d); }
- vec &rotate(const vec2 &sc, const vec &d) { return rotate(sc.x, sc.y, d); }
-
- void orthogonal(const vec &d)
- {
- *this = fabs(d.x) > fabs(d.z) ? vec(-d.y, d.x, 0) : vec(0, -d.z, d.y);
- }
-
- void orthonormalize(vec &s, vec &t) const
- {
- s.sub(vec(*this).mul(dot(s)));
- t.sub(vec(*this).mul(dot(t)))
- .sub(vec(s).mul(s.dot(t)));
- }
-
- template<class T>
- bool insidebb(const T &bbmin, const T &bbmax) const
- {
- return x >= bbmin.x && x <= bbmax.x && y >= bbmin.y && y <= bbmax.y && z >= bbmin.z && z <= bbmax.z;
- }
-
- template<class T, class U>
- bool insidebb(const T &o, U size) const
- {
- return x >= o.x && x <= o.x + size && y >= o.y && y <= o.y + size && z >= o.z && z <= o.z + size;
- }
-
- template<class T> float dist_to_bb(const T &min, const T &max) const
- {
- float sqrdist = 0;
- loopi(3)
- {
- if (v[i] < min[i]) { float delta = v[i]-min[i]; sqrdist += delta*delta; }
- else if(v[i] > max[i]) { float delta = max[i]-v[i]; sqrdist += delta*delta; }
- }
- return sqrtf(sqrdist);
- }
-
- template<class T, class S> float dist_to_bb(const T &o, S size) const
- {
- return dist_to_bb(o, T(o).add(size));
- }
-
- static vec hexcolor(int color)
- {
- return vec(((color>>16)&0xFF)*(1.0f/255.0f), ((color>>8)&0xFF)*(1.0f/255.0f), (color&0xFF)*(1.0f/255.0f));
- }
- int tohexcolor() const { return (int(::clamp(r, 0.0f, 1.0f)*255)<<16)|(int(::clamp(g, 0.0f, 1.0f)*255)<<8)|int(::clamp(b, 0.0f, 1.0f)*255); }
+ union
+ {
+ struct { float x, y, z; };
+ struct { float r, g, b; };
+ float v[3];
+ };
+
+ vec() {}
+ explicit vec(int a) : x(a), y(a), z(a) {}
+ explicit vec(float a) : x(a), y(a), z(a) {}
+ vec(float a, float b, float c) : x(a), y(b), z(c) {}
+ explicit vec(int v[3]) : x(v[0]), y(v[1]), z(v[2]) {}
+ explicit vec(const float *v) : x(v[0]), y(v[1]), z(v[2]) {}
+ explicit vec(const vec2 &v, float z = 0) : x(v.x), y(v.y), z(z) {}
+ explicit vec(const vec4 &v);
+ explicit vec(const ivec &v);
+
+ vec(float yaw, float pitch) : x(-sinf(yaw)*cosf(pitch)), y(cosf(yaw)*cosf(pitch)), z(sinf(pitch)) {}
+
+ float &operator[](int i) { return v[i]; }
+ float operator[](int i) const { return v[i]; }
+
+ vec &set(int i, float f) { v[i] = f; return *this; }
+
+ bool operator==(const vec &o) const { return x == o.x && y == o.y && z == o.z; }
+ bool operator!=(const vec &o) const { return x != o.x || y != o.y || z != o.z; }
+
+ bool iszero() const { return x==0 && y==0 && z==0; }
+ float squaredlen() const { return x*x + y*y + z*z; }
+ template<class T> float dot2(const T &o) const { return x*o.x + y*o.y; }
+ float dot(const vec &o) const { return x*o.x + y*o.y + z*o.z; }
+ float absdot(const vec &o) const { return fabs(x*o.x) + fabs(y*o.y) + fabs(z*o.z); }
+ vec &pow(float f) { x = ::pow(x, f); y = ::pow(y, f); z = ::pow(z, f); return *this; }
+ vec &exp() { x = ::exp(x); y = ::exp(y); z = ::exp(z); return *this; }
+ vec &exp2() { x = ::exp2(x); y = ::exp2(y); z = ::exp2(z); return *this; }
+ vec &sqrt() { x = sqrtf(x); y = sqrtf(y); z = sqrtf(z); return *this; }
+ vec &mul(const vec &o) { x *= o.x; y *= o.y; z *= o.z; return *this; }
+ vec &mul(float f) { x *= f; y *= f; z *= f; return *this; }
+ vec &square() { mul(*this); return *this; }
+ vec &div(const vec &o) { x /= o.x; y /= o.y; z /= o.z; return *this; }
+ vec &div(float f) { x /= f; y /= f; z /= f; return *this; }
+ vec &recip() { x = 1/x; y = 1/y; z = 1/z; return *this; }
+ vec &add(const vec &o) { x += o.x; y += o.y; z += o.z; return *this; }
+ vec &add(float f) { x += f; y += f; z += f; return *this; }
+ vec &add2(float f) { x += f; y += f; return *this; }
+ vec &addz(float f) { z += f; return *this; }
+ vec &sub(const vec &o) { x -= o.x; y -= o.y; z -= o.z; return *this; }
+ vec &sub(float f) { x -= f; y -= f; z -= f; return *this; }
+ vec &sub2(float f) { x -= f; y -= f; return *this; }
+ vec &subz(float f) { z -= f; return *this; }
+ vec &neg2() { x = -x; y = -y; return *this; }
+ vec &neg() { x = -x; y = -y; z = -z; return *this; }
+ vec &min(const vec &o) { x = ::min(x, o.x); y = ::min(y, o.y); z = ::min(z, o.z); return *this; }
+ vec &max(const vec &o) { x = ::max(x, o.x); y = ::max(y, o.y); z = ::max(z, o.z); return *this; }
+ vec &min(float f) { x = ::min(x, f); y = ::min(y, f); z = ::min(z, f); return *this; }
+ vec &max(float f) { x = ::max(x, f); y = ::max(y, f); z = ::max(z, f); return *this; }
+ vec &clamp(float f, float h) { x = ::clamp(x, f, h); y = ::clamp(y, f, h); z = ::clamp(z, f, h); return *this; }
+ vec &abs() { x = fabs(x); y = fabs(y); z = fabs(z); return *this; }
+ float magnitude2() const { return sqrtf(dot2(*this)); }
+ float magnitude() const { return sqrtf(squaredlen()); }
+ vec &normalize() { div(magnitude()); return *this; }
+ vec &safenormalize() { float m = magnitude(); if(m) div(m); return *this; }
+ bool isnormalized() const { float m = squaredlen(); return (m>0.99f && m<1.01f); }
+ float squaredist(const vec &e) const { return vec(*this).sub(e).squaredlen(); }
+ float dist(const vec &e) const { vec t; return dist(e, t); }
+ float dist(const vec &e, vec &t) const { t = *this; t.sub(e); return t.magnitude(); }
+ float dist2(const vec &o) const { float dx = x-o.x, dy = y-o.y; return sqrtf(dx*dx + dy*dy); }
+ bool reject(const vec &o, float r) { return x>o.x+r || x<o.x-r || y>o.y+r || y<o.y-r; }
+ template<class A, class B>
+ vec &cross(const A &a, const B &b) { x = a.y*b.z-a.z*b.y; y = a.z*b.x-a.x*b.z; z = a.x*b.y-a.y*b.x; return *this; }
+ vec &cross(const vec &o, const vec &a, const vec &b) { return cross(vec(a).sub(o), vec(b).sub(o)); }
+ float scalartriple(const vec &a, const vec &b) const { return x*(a.y*b.z-a.z*b.y) + y*(a.z*b.x-a.x*b.z) + z*(a.x*b.y-a.y*b.x); }
+ vec &reflectz(float rz) { z = 2*rz - z; return *this; }
+ vec &reflect(const vec &n) { float k = 2*dot(n); x -= k*n.x; y -= k*n.y; z -= k*n.z; return *this; }
+ vec &project(const vec &n) { float k = dot(n); x -= k*n.x; y -= k*n.y; z -= k*n.z; return *this; }
+ vec &projectxydir(const vec &n) { if(n.z) z = -(x*n.x/n.z + y*n.y/n.z); return *this; }
+ vec &projectxy(const vec &n)
+ {
+ float m = squaredlen(), k = dot(n);
+ projectxydir(n);
+ rescale(sqrtf(::max(m - k*k, 0.0f)));
+ return *this;
+ }
+ vec &projectxy(const vec &n, float threshold)
+ {
+ float m = squaredlen(), k = ::min(dot(n), threshold);
+ projectxydir(n);
+ rescale(sqrtf(::max(m - k*k, 0.0f)));
+ return *this;
+ }
+ vec &lerp(const vec &b, float t) { x += (b.x-x)*t; y += (b.y-y)*t; z += (b.z-z)*t; return *this; }
+ vec &lerp(const vec &a, const vec &b, float t) { x = a.x + (b.x-a.x)*t; y = a.y + (b.y-a.y)*t; z = a.z + (b.z-a.z)*t; return *this; }
+ template<class B> vec &madd(const vec &a, const B &b) { return add(vec(a).mul(b)); }
+ template<class B> vec &msub(const vec &a, const B &b) { return sub(vec(a).mul(b)); }
+
+ vec &rescale(float k)
+ {
+ float mag = magnitude();
+ if(mag > 1e-6f) mul(k / mag);
+ return *this;
+ }
+
+ vec &rotate_around_z(float c, float s) { float rx = x, ry = y; x = c*rx-s*ry; y = c*ry+s*rx; return *this; }
+ vec &rotate_around_x(float c, float s) { float ry = y, rz = z; y = c*ry-s*rz; z = c*rz+s*ry; return *this; }
+ vec &rotate_around_y(float c, float s) { float rx = x, rz = z; x = c*rx+s*rz; z = c*rz-s*rx; return *this; }
+
+ vec &rotate_around_z(float angle) { return rotate_around_z(cosf(angle), sinf(angle)); }
+ vec &rotate_around_x(float angle) { return rotate_around_x(cosf(angle), sinf(angle)); }
+ vec &rotate_around_y(float angle) { return rotate_around_y(cosf(angle), sinf(angle)); }
+
+ vec &rotate_around_z(const vec2 &sc) { return rotate_around_z(sc.x, sc.y); }
+ vec &rotate_around_x(const vec2 &sc) { return rotate_around_x(sc.x, sc.y); }
+ vec &rotate_around_y(const vec2 &sc) { return rotate_around_y(sc.x, sc.y); }
+
+ vec &rotate(float c, float s, const vec &d)
+ {
+ *this = vec(x*(d.x*d.x*(1-c)+c) + y*(d.x*d.y*(1-c)-d.z*s) + z*(d.x*d.z*(1-c)+d.y*s),
+ x*(d.y*d.x*(1-c)+d.z*s) + y*(d.y*d.y*(1-c)+c) + z*(d.y*d.z*(1-c)-d.x*s),
+ x*(d.x*d.z*(1-c)-d.y*s) + y*(d.y*d.z*(1-c)+d.x*s) + z*(d.z*d.z*(1-c)+c));
+ return *this;
+ }
+ vec &rotate(float angle, const vec &d) { return rotate(cosf(angle), sinf(angle), d); }
+ vec &rotate(const vec2 &sc, const vec &d) { return rotate(sc.x, sc.y, d); }
+
+ void orthogonal(const vec &d)
+ {
+ *this = fabs(d.x) > fabs(d.z) ? vec(-d.y, d.x, 0) : vec(0, -d.z, d.y);
+ }
+
+ void orthonormalize(vec &s, vec &t) const
+ {
+ s.sub(vec(*this).mul(dot(s)));
+ t.sub(vec(*this).mul(dot(t)))
+ .sub(vec(s).mul(s.dot(t)));
+ }
+
+ template<class T>
+ bool insidebb(const T &bbmin, const T &bbmax) const
+ {
+ return x >= bbmin.x && x <= bbmax.x && y >= bbmin.y && y <= bbmax.y && z >= bbmin.z && z <= bbmax.z;
+ }
+
+ template<class T, class U>
+ bool insidebb(const T &o, U size) const
+ {
+ return x >= o.x && x <= o.x + size && y >= o.y && y <= o.y + size && z >= o.z && z <= o.z + size;
+ }
+
+ template<class T> float dist_to_bb(const T &min, const T &max) const
+ {
+ float sqrdist = 0;
+ loopi(3)
+ {
+ if (v[i] < min[i]) { float delta = v[i]-min[i]; sqrdist += delta*delta; }
+ else if(v[i] > max[i]) { float delta = max[i]-v[i]; sqrdist += delta*delta; }
+ }
+ return sqrtf(sqrdist);
+ }
+
+ template<class T, class S> float dist_to_bb(const T &o, S size) const
+ {
+ return dist_to_bb(o, T(o).add(size));
+ }
+
+ static vec hexcolor(int color)
+ {
+ return vec(((color>>16)&0xFF)*(1.0f/255.0f), ((color>>8)&0xFF)*(1.0f/255.0f), (color&0xFF)*(1.0f/255.0f));
+ }
+ int tohexcolor() const { return (int(::clamp(r, 0.0f, 1.0f)*255)<<16)|(int(::clamp(g, 0.0f, 1.0f)*255)<<8)|int(::clamp(b, 0.0f, 1.0f)*255); }
};
inline vec2::vec2(const vec &v) : x(v.x), y(v.y) {}
static inline bool htcmp(const vec &x, const vec &y)
{
- return x == y;
+ return x == y;
}
static inline uint hthash(const vec &k)
{
- union { uint i; float f; } x, y, z;
- x.f = k.x; y.f = k.y; z.f = k.z;
- uint v = x.i^y.i^z.i;
- return v + (v>>12);
+ union { uint i; float f; } x, y, z;
+ x.f = k.x; y.f = k.y; z.f = k.z;
+ uint v = x.i^y.i^z.i;
+ return v + (v>>12);
}
struct vec4
{
- union
- {
- struct { float x, y, z, w; };
- struct { float r, g, b, a; };
- float v[4];
- };
-
- vec4() {}
- explicit vec4(const vec &p, float w = 0) : x(p.x), y(p.y), z(p.z), w(w) {}
- vec4(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) {}
- explicit vec4(const float *v) : x(v[0]), y(v[1]), z(v[2]), w(v[3]) {}
-
- float &operator[](int i) { return v[i]; }
- float operator[](int i) const { return v[i]; }
-
- template<class T> float dot3(const T &o) const { return x*o.x + y*o.y + z*o.z; }
- float dot(const vec4 &o) const { return dot3(o) + w*o.w; }
- float dot(const vec &o) const { return x*o.x + y*o.y + z*o.z + w; }
- float squaredlen() const { return dot(*this); }
- float magnitude() const { return sqrtf(squaredlen()); }
- float magnitude3() const { return sqrtf(dot3(*this)); }
- vec4 &normalize() { mul(1/magnitude()); return *this; }
- vec4 &safenormalize() { float m = magnitude(); if(m) mul(1/m); return *this; }
-
- vec4 &lerp(const vec4 &b, float t)
- {
- x += (b.x-x)*t;
- y += (b.y-y)*t;
- z += (b.z-z)*t;
- w += (b.w-w)*t;
- return *this;
- }
- vec4 &lerp(const vec4 &a, const vec4 &b, float t)
- {
- x = a.x+(b.x-a.x)*t;
- y = a.y+(b.y-a.y)*t;
- z = a.z+(b.z-a.z)*t;
- w = a.w+(b.w-a.w)*t;
- return *this;
- }
-
- vec4 &mul3(float f) { x *= f; y *= f; z *= f; return *this; }
- vec4 &mul(float f) { mul3(f); w *= f; return *this; }
- vec4 &mul(const vec4 &o) { x *= o.x; y *= o.y; z *= o.z; w *= o.w; return *this; }
- vec4 &square() { mul(*this); return *this; }
- vec4 &div3(float f) { x /= f; y /= f; z /= f; return *this; }
- vec4 &div(float f) { div3(f); w /= f; return *this; }
- vec4 &div(const vec4 &o) { x /= o.x; y /= o.y; z /= o.z; w /= o.w; return *this; }
- vec4 &recip() { x = 1/x; y = 1/y; z = 1/z; w = 1/w; return *this; }
- vec4 &add(const vec4 &o) { x += o.x; y += o.y; z += o.z; w += o.w; return *this; }
- vec4 &addw(float f) { w += f; return *this; }
- vec4 &sub(const vec4 &o) { x -= o.x; y -= o.y; z -= o.z; w -= o.w; return *this; }
- vec4 &subw(float f) { w -= f; return *this; }
- vec4 &neg3() { x = -x; y = -y; z = -z; return *this; }
- vec4 &neg() { neg3(); w = -w; return *this; }
- template<class B> vec4 &madd(const vec4 &a, const B &b) { return add(vec4(a).mul(b)); }
- template<class B> vec4 &msub(const vec4 &a, const B &b) { return sub(vec4(a).mul(b)); }
-
- void setxyz(const vec &v) { x = v.x; y = v.y; z = v.z; }
-
- vec4 &rotate_around_z(float c, float s) { float rx = x, ry = y; x = c*rx-s*ry; y = c*ry+s*rx; return *this; }
- vec4 &rotate_around_x(float c, float s) { float ry = y, rz = z; y = c*ry-s*rz; z = c*rz+s*ry; return *this; }
- vec4 &rotate_around_y(float c, float s) { float rx = x, rz = z; x = c*rx+s*rz; z = c*rz-s*rx; return *this; }
-
- vec4 &rotate_around_z(float angle) { return rotate_around_z(cosf(angle), sinf(angle)); }
- vec4 &rotate_around_x(float angle) { return rotate_around_x(cosf(angle), sinf(angle)); }
- vec4 &rotate_around_y(float angle) { return rotate_around_y(cosf(angle), sinf(angle)); }
+ union
+ {
+ struct { float x, y, z, w; };
+ struct { float r, g, b, a; };
+ float v[4];
+ };
+
+ vec4() {}
+ explicit vec4(const vec &p, float w = 0) : x(p.x), y(p.y), z(p.z), w(w) {}
+ vec4(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) {}
+ explicit vec4(const float *v) : x(v[0]), y(v[1]), z(v[2]), w(v[3]) {}
+
+ float &operator[](int i) { return v[i]; }
+ float operator[](int i) const { return v[i]; }
+
+ template<class T> float dot3(const T &o) const { return x*o.x + y*o.y + z*o.z; }
+ float dot(const vec4 &o) const { return dot3(o) + w*o.w; }
+ float dot(const vec &o) const { return x*o.x + y*o.y + z*o.z + w; }
+ float squaredlen() const { return dot(*this); }
+ float magnitude() const { return sqrtf(squaredlen()); }
+ float magnitude3() const { return sqrtf(dot3(*this)); }
+ vec4 &normalize() { mul(1/magnitude()); return *this; }
+ vec4 &safenormalize() { float m = magnitude(); if(m) mul(1/m); return *this; }
+
+ vec4 &lerp(const vec4 &b, float t)
+ {
+ x += (b.x-x)*t;
+ y += (b.y-y)*t;
+ z += (b.z-z)*t;
+ w += (b.w-w)*t;
+ return *this;
+ }
+ vec4 &lerp(const vec4 &a, const vec4 &b, float t)
+ {
+ x = a.x+(b.x-a.x)*t;
+ y = a.y+(b.y-a.y)*t;
+ z = a.z+(b.z-a.z)*t;
+ w = a.w+(b.w-a.w)*t;
+ return *this;
+ }
+
+ vec4 &mul3(float f) { x *= f; y *= f; z *= f; return *this; }
+ vec4 &mul(float f) { mul3(f); w *= f; return *this; }
+ vec4 &mul(const vec4 &o) { x *= o.x; y *= o.y; z *= o.z; w *= o.w; return *this; }
+ vec4 &square() { mul(*this); return *this; }
+ vec4 &div3(float f) { x /= f; y /= f; z /= f; return *this; }
+ vec4 &div(float f) { div3(f); w /= f; return *this; }
+ vec4 &div(const vec4 &o) { x /= o.x; y /= o.y; z /= o.z; w /= o.w; return *this; }
+ vec4 &recip() { x = 1/x; y = 1/y; z = 1/z; w = 1/w; return *this; }
+ vec4 &add(const vec4 &o) { x += o.x; y += o.y; z += o.z; w += o.w; return *this; }
+ vec4 &addw(float f) { w += f; return *this; }
+ vec4 &sub(const vec4 &o) { x -= o.x; y -= o.y; z -= o.z; w -= o.w; return *this; }
+ vec4 &subw(float f) { w -= f; return *this; }
+ vec4 &neg3() { x = -x; y = -y; z = -z; return *this; }
+ vec4 &neg() { neg3(); w = -w; return *this; }
+ template<class B> vec4 &madd(const vec4 &a, const B &b) { return add(vec4(a).mul(b)); }
+ template<class B> vec4 &msub(const vec4 &a, const B &b) { return sub(vec4(a).mul(b)); }
+
+ void setxyz(const vec &v) { x = v.x; y = v.y; z = v.z; }
+
+ vec4 &rotate_around_z(float c, float s) { float rx = x, ry = y; x = c*rx-s*ry; y = c*ry+s*rx; return *this; }
+ vec4 &rotate_around_x(float c, float s) { float ry = y, rz = z; y = c*ry-s*rz; z = c*rz+s*ry; return *this; }
+ vec4 &rotate_around_y(float c, float s) { float rx = x, rz = z; x = c*rx+s*rz; z = c*rz-s*rx; return *this; }
+
+ vec4 &rotate_around_z(float angle) { return rotate_around_z(cosf(angle), sinf(angle)); }
+ vec4 &rotate_around_x(float angle) { return rotate_around_x(cosf(angle), sinf(angle)); }
+ vec4 &rotate_around_y(float angle) { return rotate_around_y(cosf(angle), sinf(angle)); }
};
inline vec::vec(const vec4 &v) : x(v.x), y(v.y), z(v.z) {}
@@ -334,774 +334,774 @@ struct matrix4;
struct quat : vec4
{
- quat() {}
- quat(float x, float y, float z, float w) : vec4(x, y, z, w) {}
- quat(const vec &axis, float angle)
- {
- w = cosf(angle/2);
- float s = sinf(angle/2);
- x = s*axis.x;
- y = s*axis.y;
- z = s*axis.z;
- }
- explicit quat(const vec &v)
- {
- x = v.x;
- y = v.y;
- z = v.z;
- restorew();
- }
- explicit quat(const matrix3 &m) { convertmatrix(m); }
- explicit quat(const matrix4x3 &m) { convertmatrix(m); }
- explicit quat(const matrix4 &m) { convertmatrix(m); }
-
- void restorew() { w = 1.0f-x*x-y*y-z*z; w = w<0 ? 0 : -sqrtf(w); }
-
- quat &add(const vec4 &o) { vec4::add(o); return *this; }
- quat &sub(const vec4 &o) { vec4::sub(o); return *this; }
- quat &mul(float k) { vec4::mul(k); return *this; }
-
- quat &mul(const quat &p, const quat &o)
- {
- x = p.w*o.x + p.x*o.w + p.y*o.z - p.z*o.y;
- y = p.w*o.y - p.x*o.z + p.y*o.w + p.z*o.x;
- z = p.w*o.z + p.x*o.y - p.y*o.x + p.z*o.w;
- w = p.w*o.w - p.x*o.x - p.y*o.y - p.z*o.z;
- return *this;
- }
- quat &mul(const quat &o) { return mul(quat(*this), o); }
-
- quat &invert() { neg3(); return *this; }
-
- void calcangleaxis(float &angle, vec &axis)
- {
- float rr = dot3(*this);
- if(rr>0)
- {
- angle = 2*acosf(w);
- axis = vec(x, y, z).mul(1/rr);
- }
- else { angle = 0; axis = vec(0, 0, 1); }
- }
-
- vec rotate(const vec &v) const
- {
- return vec().cross(*this, vec().cross(*this, v).add(vec(v).mul(w))).mul(2).add(v);
- }
-
- vec invertedrotate(const vec &v) const
- {
- return vec().cross(*this, vec().cross(*this, v).sub(vec(v).mul(w))).mul(2).add(v);
- }
-
- template<class M>
- void convertmatrix(const M &m)
- {
- float trace = m.a.x + m.b.y + m.c.z;
- if(trace>0)
- {
- float r = sqrtf(1 + trace), inv = 0.5f/r;
- w = 0.5f*r;
- x = (m.b.z - m.c.y)*inv;
- y = (m.c.x - m.a.z)*inv;
- z = (m.a.y - m.b.x)*inv;
- }
- else if(m.a.x > m.b.y && m.a.x > m.c.z)
- {
- float r = sqrtf(1 + m.a.x - m.b.y - m.c.z), inv = 0.5f/r;
- x = 0.5f*r;
- y = (m.a.y + m.b.x)*inv;
- z = (m.c.x + m.a.z)*inv;
- w = (m.b.z - m.c.y)*inv;
- }
- else if(m.b.y > m.c.z)
- {
- float r = sqrtf(1 + m.b.y - m.a.x - m.c.z), inv = 0.5f/r;
- x = (m.a.y + m.b.x)*inv;
- y = 0.5f*r;
- z = (m.b.z + m.c.y)*inv;
- w = (m.c.x - m.a.z)*inv;
- }
- else
- {
- float r = sqrtf(1 + m.c.z - m.a.x - m.b.y), inv = 0.5f/r;
- x = (m.c.x + m.a.z)*inv;
- y = (m.b.z + m.c.y)*inv;
- z = 0.5f*r;
- w = (m.a.y - m.b.x)*inv;
- }
- }
+ quat() {}
+ quat(float x, float y, float z, float w) : vec4(x, y, z, w) {}
+ quat(const vec &axis, float angle)
+ {
+ w = cosf(angle/2);
+ float s = sinf(angle/2);
+ x = s*axis.x;
+ y = s*axis.y;
+ z = s*axis.z;
+ }
+ explicit quat(const vec &v)
+ {
+ x = v.x;
+ y = v.y;
+ z = v.z;
+ restorew();
+ }
+ explicit quat(const matrix3 &m) { convertmatrix(m); }
+ explicit quat(const matrix4x3 &m) { convertmatrix(m); }
+ explicit quat(const matrix4 &m) { convertmatrix(m); }
+
+ void restorew() { w = 1.0f-x*x-y*y-z*z; w = w<0 ? 0 : -sqrtf(w); }
+
+ quat &add(const vec4 &o) { vec4::add(o); return *this; }
+ quat &sub(const vec4 &o) { vec4::sub(o); return *this; }
+ quat &mul(float k) { vec4::mul(k); return *this; }
+
+ quat &mul(const quat &p, const quat &o)
+ {
+ x = p.w*o.x + p.x*o.w + p.y*o.z - p.z*o.y;
+ y = p.w*o.y - p.x*o.z + p.y*o.w + p.z*o.x;
+ z = p.w*o.z + p.x*o.y - p.y*o.x + p.z*o.w;
+ w = p.w*o.w - p.x*o.x - p.y*o.y - p.z*o.z;
+ return *this;
+ }
+ quat &mul(const quat &o) { return mul(quat(*this), o); }
+
+ quat &invert() { neg3(); return *this; }
+
+ void calcangleaxis(float &angle, vec &axis)
+ {
+ float rr = dot3(*this);
+ if(rr>0)
+ {
+ angle = 2*acosf(w);
+ axis = vec(x, y, z).mul(1/rr);
+ }
+ else { angle = 0; axis = vec(0, 0, 1); }
+ }
+
+ vec rotate(const vec &v) const
+ {
+ return vec().cross(*this, vec().cross(*this, v).add(vec(v).mul(w))).mul(2).add(v);
+ }
+
+ vec invertedrotate(const vec &v) const
+ {
+ return vec().cross(*this, vec().cross(*this, v).sub(vec(v).mul(w))).mul(2).add(v);
+ }
+
+ template<class M>
+ void convertmatrix(const M &m)
+ {
+ float trace = m.a.x + m.b.y + m.c.z;
+ if(trace>0)
+ {
+ float r = sqrtf(1 + trace), inv = 0.5f/r;
+ w = 0.5f*r;
+ x = (m.b.z - m.c.y)*inv;
+ y = (m.c.x - m.a.z)*inv;
+ z = (m.a.y - m.b.x)*inv;
+ }
+ else if(m.a.x > m.b.y && m.a.x > m.c.z)
+ {
+ float r = sqrtf(1 + m.a.x - m.b.y - m.c.z), inv = 0.5f/r;
+ x = 0.5f*r;
+ y = (m.a.y + m.b.x)*inv;
+ z = (m.c.x + m.a.z)*inv;
+ w = (m.b.z - m.c.y)*inv;
+ }
+ else if(m.b.y > m.c.z)
+ {
+ float r = sqrtf(1 + m.b.y - m.a.x - m.c.z), inv = 0.5f/r;
+ x = (m.a.y + m.b.x)*inv;
+ y = 0.5f*r;
+ z = (m.b.z + m.c.y)*inv;
+ w = (m.c.x - m.a.z)*inv;
+ }
+ else
+ {
+ float r = sqrtf(1 + m.c.z - m.a.x - m.b.y), inv = 0.5f/r;
+ x = (m.c.x + m.a.z)*inv;
+ y = (m.b.z + m.c.y)*inv;
+ z = 0.5f*r;
+ w = (m.a.y - m.b.x)*inv;
+ }
+ }
};
struct dualquat
{
- quat real, dual;
-
- dualquat() {}
- dualquat(const quat &q, const vec &p)
- : real(q),
- dual(0.5f*( p.x*q.w + p.y*q.z - p.z*q.y),
- 0.5f*(-p.x*q.z + p.y*q.w + p.z*q.x),
- 0.5f*( p.x*q.y - p.y*q.x + p.z*q.w),
- -0.5f*( p.x*q.x + p.y*q.y + p.z*q.z))
- {
- }
- explicit dualquat(const quat &q) : real(q), dual(0, 0, 0, 0) {}
- explicit dualquat(const matrix4x3 &m);
-
- dualquat &mul(float k) { real.mul(k); dual.mul(k); return *this; }
- dualquat &add(const dualquat &d) { real.add(d.real); dual.add(d.dual); return *this; }
-
- dualquat &lerp(const dualquat &to, float t)
- {
- float k = real.dot(to.real) < 0 ? -t : t;
- real.mul(1-t).add(vec4(to.real).mul(k));
- dual.mul(1-t).add(vec4(to.dual).mul(k));
- return *this;
- }
- dualquat &lerp(const dualquat &from, const dualquat &to, float t)
- {
- float k = from.real.dot(to.real) < 0 ? -t : t;
- (real = from.real).mul(1-t).add(vec4(to.real).mul(k));
- (dual = from.dual).mul(1-t).add(vec4(to.dual).mul(k));
- return *this;
- }
-
- dualquat &invert()
- {
- real.invert();
- dual.invert();
- dual.sub(quat(real).mul(2*real.dot(dual)));
- return *this;
- }
-
- void mul(const dualquat &p, const dualquat &o)
- {
- real.mul(p.real, o.real);
- dual.mul(p.real, o.dual).add(quat().mul(p.dual, o.real));
- }
- void mul(const dualquat &o) { mul(dualquat(*this), o); }
-
- void mulorient(const quat &q)
- {
- real.mul(q, quat(real));
- dual.mul(quat(q).invert(), quat(dual));
- }
-
- void mulorient(const quat &q, const dualquat &base)
- {
- quat trans;
- trans.mul(base.dual, quat(base.real).invert());
- dual.mul(quat(q).invert(), quat(real).mul(trans).add(dual));
-
- real.mul(q, quat(real));
- dual.add(quat().mul(real, trans.invert())).sub(quat(real).mul(2*base.real.dot(base.dual)));
- }
-
- void normalize()
- {
- float invlen = 1/real.magnitude();
- real.mul(invlen);
- dual.mul(invlen);
- }
-
- void translate(const vec &p)
- {
- dual.x += 0.5f*( p.x*real.w + p.y*real.z - p.z*real.y);
- dual.y += 0.5f*(-p.x*real.z + p.y*real.w + p.z*real.x);
- dual.z += 0.5f*( p.x*real.y - p.y*real.x + p.z*real.w);
- dual.w += -0.5f*( p.x*real.x + p.y*real.y + p.z*real.z);
- }
-
- void scale(float k)
- {
- dual.mul(k);
- }
-
- void fixantipodal(const dualquat &d)
- {
- if(real.dot(d.real) < 0)
- {
- real.neg();
- dual.neg();
- }
- }
-
- void accumulate(const dualquat &d, float k)
- {
- if(real.dot(d.real) < 0) k = -k;
- real.add(vec4(d.real).mul(k));
- dual.add(vec4(d.dual).mul(k));
- }
-
- vec transform(const vec &v) const
- {
- return vec().cross(real, vec().cross(real, v).add(vec(v).mul(real.w)).add(vec(dual))).add(vec(dual).mul(real.w)).sub(vec(real).mul(dual.w)).mul(2).add(v);
- }
-
- quat transform(const quat &q) const
- {
- return quat().mul(real, q);
- }
-
- vec transposedtransform(const vec &v) const
- {
- return dualquat(*this).invert().transform(v);
- }
-
- vec transformnormal(const vec &v) const
- {
- return real.rotate(v);
- }
-
- vec transposedtransformnormal(const vec &v) const
- {
- return real.invertedrotate(v);
- }
-
- vec gettranslation() const
- {
- return vec().cross(real, dual).add(vec(dual).mul(real.w)).sub(vec(real).mul(dual.w)).mul(2);
- }
+ quat real, dual;
+
+ dualquat() {}
+ dualquat(const quat &q, const vec &p)
+ : real(q),
+ dual(0.5f*( p.x*q.w + p.y*q.z - p.z*q.y),
+ 0.5f*(-p.x*q.z + p.y*q.w + p.z*q.x),
+ 0.5f*( p.x*q.y - p.y*q.x + p.z*q.w),
+ -0.5f*( p.x*q.x + p.y*q.y + p.z*q.z))
+ {
+ }
+ explicit dualquat(const quat &q) : real(q), dual(0, 0, 0, 0) {}
+ explicit dualquat(const matrix4x3 &m);
+
+ dualquat &mul(float k) { real.mul(k); dual.mul(k); return *this; }
+ dualquat &add(const dualquat &d) { real.add(d.real); dual.add(d.dual); return *this; }
+
+ dualquat &lerp(const dualquat &to, float t)
+ {
+ float k = real.dot(to.real) < 0 ? -t : t;
+ real.mul(1-t).add(vec4(to.real).mul(k));
+ dual.mul(1-t).add(vec4(to.dual).mul(k));
+ return *this;
+ }
+ dualquat &lerp(const dualquat &from, const dualquat &to, float t)
+ {
+ float k = from.real.dot(to.real) < 0 ? -t : t;
+ (real = from.real).mul(1-t).add(vec4(to.real).mul(k));
+ (dual = from.dual).mul(1-t).add(vec4(to.dual).mul(k));
+ return *this;
+ }
+
+ dualquat &invert()
+ {
+ real.invert();
+ dual.invert();
+ dual.sub(quat(real).mul(2*real.dot(dual)));
+ return *this;
+ }
+
+ void mul(const dualquat &p, const dualquat &o)
+ {
+ real.mul(p.real, o.real);
+ dual.mul(p.real, o.dual).add(quat().mul(p.dual, o.real));
+ }
+ void mul(const dualquat &o) { mul(dualquat(*this), o); }
+
+ void mulorient(const quat &q)
+ {
+ real.mul(q, quat(real));
+ dual.mul(quat(q).invert(), quat(dual));
+ }
+
+ void mulorient(const quat &q, const dualquat &base)
+ {
+ quat trans;
+ trans.mul(base.dual, quat(base.real).invert());
+ dual.mul(quat(q).invert(), quat(real).mul(trans).add(dual));
+
+ real.mul(q, quat(real));
+ dual.add(quat().mul(real, trans.invert())).sub(quat(real).mul(2*base.real.dot(base.dual)));
+ }
+
+ void normalize()
+ {
+ float invlen = 1/real.magnitude();
+ real.mul(invlen);
+ dual.mul(invlen);
+ }
+
+ void translate(const vec &p)
+ {
+ dual.x += 0.5f*( p.x*real.w + p.y*real.z - p.z*real.y);
+ dual.y += 0.5f*(-p.x*real.z + p.y*real.w + p.z*real.x);
+ dual.z += 0.5f*( p.x*real.y - p.y*real.x + p.z*real.w);
+ dual.w += -0.5f*( p.x*real.x + p.y*real.y + p.z*real.z);
+ }
+
+ void scale(float k)
+ {
+ dual.mul(k);
+ }
+
+ void fixantipodal(const dualquat &d)
+ {
+ if(real.dot(d.real) < 0)
+ {
+ real.neg();
+ dual.neg();
+ }
+ }
+
+ void accumulate(const dualquat &d, float k)
+ {
+ if(real.dot(d.real) < 0) k = -k;
+ real.add(vec4(d.real).mul(k));
+ dual.add(vec4(d.dual).mul(k));
+ }
+
+ vec transform(const vec &v) const
+ {
+ return vec().cross(real, vec().cross(real, v).add(vec(v).mul(real.w)).add(vec(dual))).add(vec(dual).mul(real.w)).sub(vec(real).mul(dual.w)).mul(2).add(v);
+ }
+
+ quat transform(const quat &q) const
+ {
+ return quat().mul(real, q);
+ }
+
+ vec transposedtransform(const vec &v) const
+ {
+ return dualquat(*this).invert().transform(v);
+ }
+
+ vec transformnormal(const vec &v) const
+ {
+ return real.rotate(v);
+ }
+
+ vec transposedtransformnormal(const vec &v) const
+ {
+ return real.invertedrotate(v);
+ }
+
+ vec gettranslation() const
+ {
+ return vec().cross(real, dual).add(vec(dual).mul(real.w)).sub(vec(real).mul(dual.w)).mul(2);
+ }
};
struct matrix3
{
- vec a, b, c;
-
- matrix3() {}
- matrix3(const vec &a, const vec &b, const vec &c) : a(a), b(b), c(c) {}
- explicit matrix3(float angle, const vec &axis) { rotate(angle, axis); }
- explicit matrix3(const quat &q)
- {
- float x = q.x, y = q.y, z = q.z, w = q.w,
- tx = 2*x, ty = 2*y, tz = 2*z,
- txx = tx*x, tyy = ty*y, tzz = tz*z,
- txy = tx*y, txz = tx*z, tyz = ty*z,
- twx = w*tx, twy = w*ty, twz = w*tz;
- a = vec(1 - (tyy + tzz), txy + twz, txz - twy);
- b = vec(txy - twz, 1 - (txx + tzz), tyz + twx);
- c = vec(txz + twy, tyz - twx, 1 - (txx + tyy));
- }
- explicit matrix3(const matrix4x3 &m);
- explicit matrix3(const matrix4 &m);
-
- void mul(const matrix3 &m, const matrix3 &n)
- {
- a = vec(m.a).mul(n.a.x).madd(m.b, n.a.y).madd(m.c, n.a.z);
- b = vec(m.a).mul(n.b.x).madd(m.b, n.b.y).madd(m.c, n.b.z);
- c = vec(m.a).mul(n.c.x).madd(m.b, n.c.y).madd(m.c, n.c.z);
- }
- void mul(const matrix3 &n) { mul(matrix3(*this), n); }
-
- void multranspose(const matrix3 &m, const matrix3 &n)
- {
- a = vec(m.a).mul(n.a.x).madd(m.b, n.b.x).madd(m.c, n.c.x);
- b = vec(m.a).mul(n.a.y).madd(m.b, n.b.y).madd(m.c, n.c.y);
- c = vec(m.a).mul(n.a.z).madd(m.b, n.b.z).madd(m.c, n.c.z);
- }
- void multranspose(const matrix3 &n) { multranspose(matrix3(*this), n); }
-
- void transposemul(const matrix3 &m, const matrix3 &n)
- {
- a = vec(m.a.dot(n.a), m.b.dot(n.a), m.c.dot(n.a));
- b = vec(m.a.dot(n.b), m.b.dot(n.b), m.c.dot(n.b));
- c = vec(m.a.dot(n.c), m.b.dot(n.c), m.c.dot(n.c));
- }
- void transposemul(const matrix3 &n) { transposemul(matrix3(*this), n); }
-
- void transpose()
- {
- swap(a.y, b.x); swap(a.z, c.x);
- swap(b.z, c.y);
- }
-
- template<class M>
- void transpose(const M &m)
- {
- a = vec(m.a.x, m.b.x, m.c.x);
- b = vec(m.a.y, m.b.y, m.c.y);
- c = vec(m.a.z, m.b.z, m.c.z);
- }
-
- void invert(const matrix3 &o)
- {
- vec unscale(1/o.a.squaredlen(), 1/o.b.squaredlen(), 1/o.c.squaredlen());
- transpose(o);
- a.mul(unscale);
- b.mul(unscale);
- c.mul(unscale);
- }
- void invert() { invert(matrix3(*this)); }
-
- void normalize()
- {
- a.normalize();
- b.normalize();
- c.normalize();
- }
-
- void scale(float k)
- {
- a.mul(k);
- b.mul(k);
- c.mul(k);
- }
-
- void rotate(float angle, const vec &axis)
- {
- rotate(cosf(angle), sinf(angle), axis);
- }
-
- void rotate(float ck, float sk, const vec &axis)
- {
- a = vec(axis.x*axis.x*(1-ck)+ck, axis.x*axis.y*(1-ck)+axis.z*sk, axis.x*axis.z*(1-ck)-axis.y*sk);
- b = vec(axis.x*axis.y*(1-ck)-axis.z*sk, axis.y*axis.y*(1-ck)+ck, axis.y*axis.z*(1-ck)+axis.x*sk);
- c = vec(axis.x*axis.z*(1-ck)+axis.y*sk, axis.y*axis.z*(1-ck)-axis.x*sk, axis.z*axis.z*(1-ck)+ck);
- }
-
- void setyaw(float ck, float sk)
- {
- a = vec(ck, sk, 0);
- b = vec(-sk, ck, 0);
- c = vec(0, 0, 1);
- }
-
- void setyaw(float angle)
- {
- setyaw(cosf(angle), sinf(angle));
- }
-
- float trace() const { return a.x + b.y + c.z; }
-
- bool calcangleaxis(float tr, float &angle, vec &axis, float threshold = 1e-16f) const
- {
- if(tr <= -1)
- {
- if(a.x >= b.y && a.x >= c.z)
- {
- float r = 1 + a.x - b.y - c.z;
- if(r <= threshold) return false;
- r = sqrtf(r);
- axis.x = 0.5f*r;
- axis.y = b.x/r;
- axis.z = c.x/r;
- }
- else if(b.y >= c.z)
- {
- float r = 1 + b.y - a.x - c.z;
- if(r <= threshold) return false;
- r = sqrtf(r);
- axis.y = 0.5f*r;
- axis.x = b.x/r;
- axis.z = c.y/r;
- }
- else
- {
- float r = 1 + b.y - a.x - c.z;
- if(r <= threshold) return false;
- r = sqrtf(r);
- axis.z = 0.5f*r;
- axis.x = c.x/r;
- axis.y = c.y/r;
- }
- angle = M_PI;
- }
- else if(tr >= 3)
- {
- axis = vec(0, 0, 1);
- angle = 0;
- }
- else
- {
- axis = vec(b.z - c.y, c.x - a.z, a.y - b.x);
- float r = axis.squaredlen();
- if(r <= threshold) return false;
- axis.mul(1/sqrtf(r));
- angle = acosf(0.5f*(tr - 1));
- }
- return true;
- }
-
- bool calcangleaxis(float &angle, vec &axis, float threshold = 1e-16f) const { return calcangleaxis(trace(), angle, axis, threshold); }
-
- vec transform(const vec &o) const
- {
- return vec(a).mul(o.x).madd(b, o.y).madd(c, o.z);
- }
- vec transposedtransform(const vec &o) const { return vec(a.dot(o), b.dot(o), c.dot(o)); }
- vec abstransform(const vec &o) const
- {
- return vec(a).mul(o.x).abs().add(vec(b).mul(o.y).abs()).add(vec(c).mul(o.z).abs());
- }
- vec abstransposedtransform(const vec &o) const
- {
- return vec(a.absdot(o), b.absdot(o), c.absdot(o));
- }
-
- void identity()
- {
- a = vec(1, 0, 0);
- b = vec(0, 1, 0);
- c = vec(0, 0, 1);
- }
-
- void rotate_around_x(float ck, float sk)
- {
- vec rb = vec(b).mul(ck).madd(c, sk),
- rc = vec(c).mul(ck).msub(b, sk);
- b = rb;
- c = rc;
- }
- void rotate_around_x(float angle) { rotate_around_x(cosf(angle), sinf(angle)); }
- void rotate_around_x(const vec2 &sc) { rotate_around_x(sc.x, sc.y); }
-
- void rotate_around_y(float ck, float sk)
- {
- vec rc = vec(c).mul(ck).madd(a, sk),
- ra = vec(a).mul(ck).msub(c, sk);
- c = rc;
- a = ra;
- }
- void rotate_around_y(float angle) { rotate_around_y(cosf(angle), sinf(angle)); }
- void rotate_around_y(const vec2 &sc) { rotate_around_y(sc.x, sc.y); }
-
- void rotate_around_z(float ck, float sk)
- {
- vec ra = vec(a).mul(ck).madd(b, sk),
- rb = vec(b).mul(ck).msub(a, sk);
- a = ra;
- b = rb;
- }
- void rotate_around_z(float angle) { rotate_around_z(cosf(angle), sinf(angle)); }
- void rotate_around_z(const vec2 &sc) { rotate_around_z(sc.x, sc.y); }
-
- vec transform(const vec2 &o) { return vec(a).mul(o.x).madd(b, o.y); }
- vec transposedtransform(const vec2 &o) const { return vec(a.dot2(o), b.dot2(o), c.dot2(o)); }
-
- vec rowx() const { return vec(a.x, b.x, c.x); }
- vec rowy() const { return vec(a.y, b.y, c.y); }
- vec rowz() const { return vec(a.z, b.z, c.z); }
+ vec a, b, c;
+
+ matrix3() {}
+ matrix3(const vec &a, const vec &b, const vec &c) : a(a), b(b), c(c) {}
+ explicit matrix3(float angle, const vec &axis) { rotate(angle, axis); }
+ explicit matrix3(const quat &q)
+ {
+ float x = q.x, y = q.y, z = q.z, w = q.w,
+ tx = 2*x, ty = 2*y, tz = 2*z,
+ txx = tx*x, tyy = ty*y, tzz = tz*z,
+ txy = tx*y, txz = tx*z, tyz = ty*z,
+ twx = w*tx, twy = w*ty, twz = w*tz;
+ a = vec(1 - (tyy + tzz), txy + twz, txz - twy);
+ b = vec(txy - twz, 1 - (txx + tzz), tyz + twx);
+ c = vec(txz + twy, tyz - twx, 1 - (txx + tyy));
+ }
+ explicit matrix3(const matrix4x3 &m);
+ explicit matrix3(const matrix4 &m);
+
+ void mul(const matrix3 &m, const matrix3 &n)
+ {
+ a = vec(m.a).mul(n.a.x).madd(m.b, n.a.y).madd(m.c, n.a.z);
+ b = vec(m.a).mul(n.b.x).madd(m.b, n.b.y).madd(m.c, n.b.z);
+ c = vec(m.a).mul(n.c.x).madd(m.b, n.c.y).madd(m.c, n.c.z);
+ }
+ void mul(const matrix3 &n) { mul(matrix3(*this), n); }
+
+ void multranspose(const matrix3 &m, const matrix3 &n)
+ {
+ a = vec(m.a).mul(n.a.x).madd(m.b, n.b.x).madd(m.c, n.c.x);
+ b = vec(m.a).mul(n.a.y).madd(m.b, n.b.y).madd(m.c, n.c.y);
+ c = vec(m.a).mul(n.a.z).madd(m.b, n.b.z).madd(m.c, n.c.z);
+ }
+ void multranspose(const matrix3 &n) { multranspose(matrix3(*this), n); }
+
+ void transposemul(const matrix3 &m, const matrix3 &n)
+ {
+ a = vec(m.a.dot(n.a), m.b.dot(n.a), m.c.dot(n.a));
+ b = vec(m.a.dot(n.b), m.b.dot(n.b), m.c.dot(n.b));
+ c = vec(m.a.dot(n.c), m.b.dot(n.c), m.c.dot(n.c));
+ }
+ void transposemul(const matrix3 &n) { transposemul(matrix3(*this), n); }
+
+ void transpose()
+ {
+ swap(a.y, b.x); swap(a.z, c.x);
+ swap(b.z, c.y);
+ }
+
+ template<class M>
+ void transpose(const M &m)
+ {
+ a = vec(m.a.x, m.b.x, m.c.x);
+ b = vec(m.a.y, m.b.y, m.c.y);
+ c = vec(m.a.z, m.b.z, m.c.z);
+ }
+
+ void invert(const matrix3 &o)
+ {
+ vec unscale(1/o.a.squaredlen(), 1/o.b.squaredlen(), 1/o.c.squaredlen());
+ transpose(o);
+ a.mul(unscale);
+ b.mul(unscale);
+ c.mul(unscale);
+ }
+ void invert() { invert(matrix3(*this)); }
+
+ void normalize()
+ {
+ a.normalize();
+ b.normalize();
+ c.normalize();
+ }
+
+ void scale(float k)
+ {
+ a.mul(k);
+ b.mul(k);
+ c.mul(k);
+ }
+
+ void rotate(float angle, const vec &axis)
+ {
+ rotate(cosf(angle), sinf(angle), axis);
+ }
+
+ void rotate(float ck, float sk, const vec &axis)
+ {
+ a = vec(axis.x*axis.x*(1-ck)+ck, axis.x*axis.y*(1-ck)+axis.z*sk, axis.x*axis.z*(1-ck)-axis.y*sk);
+ b = vec(axis.x*axis.y*(1-ck)-axis.z*sk, axis.y*axis.y*(1-ck)+ck, axis.y*axis.z*(1-ck)+axis.x*sk);
+ c = vec(axis.x*axis.z*(1-ck)+axis.y*sk, axis.y*axis.z*(1-ck)-axis.x*sk, axis.z*axis.z*(1-ck)+ck);
+ }
+
+ void setyaw(float ck, float sk)
+ {
+ a = vec(ck, sk, 0);
+ b = vec(-sk, ck, 0);
+ c = vec(0, 0, 1);
+ }
+
+ void setyaw(float angle)
+ {
+ setyaw(cosf(angle), sinf(angle));
+ }
+
+ float trace() const { return a.x + b.y + c.z; }
+
+ bool calcangleaxis(float tr, float &angle, vec &axis, float threshold = 1e-16f) const
+ {
+ if(tr <= -1)
+ {
+ if(a.x >= b.y && a.x >= c.z)
+ {
+ float r = 1 + a.x - b.y - c.z;
+ if(r <= threshold) return false;
+ r = sqrtf(r);
+ axis.x = 0.5f*r;
+ axis.y = b.x/r;
+ axis.z = c.x/r;
+ }
+ else if(b.y >= c.z)
+ {
+ float r = 1 + b.y - a.x - c.z;
+ if(r <= threshold) return false;
+ r = sqrtf(r);
+ axis.y = 0.5f*r;
+ axis.x = b.x/r;
+ axis.z = c.y/r;
+ }
+ else
+ {
+ float r = 1 + b.y - a.x - c.z;
+ if(r <= threshold) return false;
+ r = sqrtf(r);
+ axis.z = 0.5f*r;
+ axis.x = c.x/r;
+ axis.y = c.y/r;
+ }
+ angle = M_PI;
+ }
+ else if(tr >= 3)
+ {
+ axis = vec(0, 0, 1);
+ angle = 0;
+ }
+ else
+ {
+ axis = vec(b.z - c.y, c.x - a.z, a.y - b.x);
+ float r = axis.squaredlen();
+ if(r <= threshold) return false;
+ axis.mul(1/sqrtf(r));
+ angle = acosf(0.5f*(tr - 1));
+ }
+ return true;
+ }
+
+ bool calcangleaxis(float &angle, vec &axis, float threshold = 1e-16f) const { return calcangleaxis(trace(), angle, axis, threshold); }
+
+ vec transform(const vec &o) const
+ {
+ return vec(a).mul(o.x).madd(b, o.y).madd(c, o.z);
+ }
+ vec transposedtransform(const vec &o) const { return vec(a.dot(o), b.dot(o), c.dot(o)); }
+ vec abstransform(const vec &o) const
+ {
+ return vec(a).mul(o.x).abs().add(vec(b).mul(o.y).abs()).add(vec(c).mul(o.z).abs());
+ }
+ vec abstransposedtransform(const vec &o) const
+ {
+ return vec(a.absdot(o), b.absdot(o), c.absdot(o));
+ }
+
+ void identity()
+ {
+ a = vec(1, 0, 0);
+ b = vec(0, 1, 0);
+ c = vec(0, 0, 1);
+ }
+
+ void rotate_around_x(float ck, float sk)
+ {
+ vec rb = vec(b).mul(ck).madd(c, sk),
+ rc = vec(c).mul(ck).msub(b, sk);
+ b = rb;
+ c = rc;
+ }
+ void rotate_around_x(float angle) { rotate_around_x(cosf(angle), sinf(angle)); }
+ void rotate_around_x(const vec2 &sc) { rotate_around_x(sc.x, sc.y); }
+
+ void rotate_around_y(float ck, float sk)
+ {
+ vec rc = vec(c).mul(ck).madd(a, sk),
+ ra = vec(a).mul(ck).msub(c, sk);
+ c = rc;
+ a = ra;
+ }
+ void rotate_around_y(float angle) { rotate_around_y(cosf(angle), sinf(angle)); }
+ void rotate_around_y(const vec2 &sc) { rotate_around_y(sc.x, sc.y); }
+
+ void rotate_around_z(float ck, float sk)
+ {
+ vec ra = vec(a).mul(ck).madd(b, sk),
+ rb = vec(b).mul(ck).msub(a, sk);
+ a = ra;
+ b = rb;
+ }
+ void rotate_around_z(float angle) { rotate_around_z(cosf(angle), sinf(angle)); }
+ void rotate_around_z(const vec2 &sc) { rotate_around_z(sc.x, sc.y); }
+
+ vec transform(const vec2 &o) { return vec(a).mul(o.x).madd(b, o.y); }
+ vec transposedtransform(const vec2 &o) const { return vec(a.dot2(o), b.dot2(o), c.dot2(o)); }
+
+ vec rowx() const { return vec(a.x, b.x, c.x); }
+ vec rowy() const { return vec(a.y, b.y, c.y); }
+ vec rowz() const { return vec(a.z, b.z, c.z); }
};
struct matrix4x3
{
- vec a, b, c, d;
-
- matrix4x3() {}
- matrix4x3(const vec &a, const vec &b, const vec &c, const vec &d) : a(a), b(b), c(c), d(d) {}
- matrix4x3(const matrix3 &rot, const vec &trans) : a(rot.a), b(rot.b), c(rot.c), d(trans) {}
- matrix4x3(const dualquat &dq)
- {
- vec4 r = vec4(dq.real).mul(1/dq.real.squaredlen()), rr = vec4(r).mul(dq.real);
- r.mul(2);
- float xy = r.x*dq.real.y, xz = r.x*dq.real.z, yz = r.y*dq.real.z,
- wx = r.w*dq.real.x, wy = r.w*dq.real.y, wz = r.w*dq.real.z;
- a = vec(rr.w + rr.x - rr.y - rr.z, xy + wz, xz - wy);
- b = vec(xy - wz, rr.w + rr.y - rr.x - rr.z, yz + wx);
- c = vec(xz + wy, yz - wx, rr.w + rr.z - rr.x - rr.y);
- d = vec(-(dq.dual.w*r.x - dq.dual.x*r.w + dq.dual.y*r.z - dq.dual.z*r.y),
- -(dq.dual.w*r.y - dq.dual.x*r.z - dq.dual.y*r.w + dq.dual.z*r.x),
- -(dq.dual.w*r.z + dq.dual.x*r.y - dq.dual.y*r.x - dq.dual.z*r.w));
-
- }
- explicit matrix4x3(const matrix4 &m);
-
- void mul(float k)
- {
- a.mul(k);
- b.mul(k);
- c.mul(k);
- d.mul(k);
- }
-
- void setscale(float x, float y, float z) { a.x = x; b.y = y; c.z = z; }
- void setscale(const vec &v) { setscale(v.x, v.y, v.z); }
- void setscale(float n) { setscale(n, n, n); }
-
- void scale(float x, float y, float z)
- {
- a.mul(x);
- b.mul(y);
- c.mul(z);
- }
- void scale(const vec &v) { scale(v.x, v.y, v.z); }
- void scale(float n) { scale(n, n, n); }
-
- void settranslation(const vec &p) { d = p; }
- void settranslation(float x, float y, float z) { d = vec(x, y, z); }
-
- void translate(const vec &p) { d.madd(a, p.x).madd(b, p.y).madd(c, p.z); }
- void translate(float x, float y, float z) { translate(vec(x, y, z)); }
- void translate(const vec &p, float scale) { translate(vec(p).mul(scale)); }
-
- void posttranslate(const vec &p) { d.add(p); }
- void posttranslate(float x, float y, float z) { posttranslate(vec(x, y, z)); }
- void posttranslate(const vec &p, float scale) { d.madd(p, scale); }
-
- void accumulate(const matrix4x3 &m, float k)
- {
- a.madd(m.a, k);
- b.madd(m.b, k);
- c.madd(m.c, k);
- d.madd(m.d, k);
- }
-
- void normalize()
- {
- a.normalize();
- b.normalize();
- c.normalize();
- }
-
- void lerp(const matrix4x3 &to, float t)
- {
- a.lerp(to.a, t);
- b.lerp(to.b, t);
- c.lerp(to.c, t);
- d.lerp(to.d, t);
- }
- void lerp(const matrix4x3 &from, const matrix4x3 &to, float t)
- {
- a.lerp(from.a, to.a, t);
- b.lerp(from.b, to.b, t);
- c.lerp(from.c, to.c, t);
- d.lerp(from.d, to.d, t);
- }
-
- void identity()
- {
- a = vec(1, 0, 0);
- b = vec(0, 1, 0);
- c = vec(0, 0, 1);
- d = vec(0, 0, 0);
- }
-
- void mul(const matrix4x3 &m, const matrix4x3 &n)
- {
- a = vec(m.a).mul(n.a.x).madd(m.b, n.a.y).madd(m.c, n.a.z);
- b = vec(m.a).mul(n.b.x).madd(m.b, n.b.y).madd(m.c, n.b.z);
- c = vec(m.a).mul(n.c.x).madd(m.b, n.c.y).madd(m.c, n.c.z);
- d = vec(m.d).madd(m.a, n.d.x).madd(m.b, n.d.y).madd(m.c, n.d.z);
- }
- void mul(const matrix4x3 &n) { mul(matrix4x3(*this), n); }
-
- void mul(const matrix3 &m, const matrix4x3 &n)
- {
- a = vec(m.a).mul(n.a.x).madd(m.b, n.a.y).madd(m.c, n.a.z);
- b = vec(m.a).mul(n.b.x).madd(m.b, n.b.y).madd(m.c, n.b.z);
- c = vec(m.a).mul(n.c.x).madd(m.b, n.c.y).madd(m.c, n.c.z);
- d = vec(m.a).mul(n.d.x).madd(m.b, n.d.y).madd(m.c, n.d.z);
- }
-
- void mul(const matrix3 &rot, const vec &trans, const matrix4x3 &n)
- {
- mul(rot, n);
- d.add(trans);
- }
-
- void transpose()
- {
- d = vec(a.dot(d), b.dot(d), c.dot(d)).neg();
- swap(a.y, b.x); swap(a.z, c.x);
- swap(b.z, c.y);
- }
-
- void transpose(const matrix4x3 &o)
- {
- a = vec(o.a.x, o.b.x, o.c.x);
- b = vec(o.a.y, o.b.y, o.c.y);
- c = vec(o.a.z, o.b.z, o.c.z);
- d = vec(o.a.dot(o.d), o.b.dot(o.d), o.c.dot(o.d)).neg();
- }
-
- void transposemul(const matrix4x3 &m, const matrix4x3 &n)
- {
- vec t(m.a.dot(m.d), m.b.dot(m.d), m.c.dot(m.d));
- a = vec(m.a.dot(n.a), m.b.dot(n.a), m.c.dot(n.a));
- b = vec(m.a.dot(n.b), m.b.dot(n.b), m.c.dot(n.b));
- c = vec(m.a.dot(n.c), m.b.dot(n.c), m.c.dot(n.c));
- d = vec(m.a.dot(n.d), m.b.dot(n.d), m.c.dot(n.d)).sub(t);
- }
-
- void multranspose(const matrix4x3 &m, const matrix4x3 &n)
- {
- vec t(n.a.dot(n.d), n.b.dot(n.d), n.c.dot(n.d));
- a = vec(m.a).mul(n.a.x).madd(m.b, n.b.x).madd(m.c, n.c.x);
- b = vec(m.a).mul(n.a.y).madd(m.b, n.b.y).madd(m.c, n.c.y);
- c = vec(m.a).mul(n.a.z).madd(m.b, n.b.z).madd(m.c, n.c.z);
- d = vec(m.d).msub(m.a, t.x).msub(m.b, t.y).msub(m.c, t.z);
- }
-
- void invert(const matrix4x3 &o)
- {
- vec unscale(1/o.a.squaredlen(), 1/o.b.squaredlen(), 1/o.c.squaredlen());
- transpose(o);
- a.mul(unscale);
- b.mul(unscale);
- c.mul(unscale);
- d.mul(unscale);
- }
- void invert() { invert(matrix4x3(*this)); }
-
- void rotate(float angle, const vec &d)
- {
- rotate(cosf(angle), sinf(angle), d);
- }
-
- void rotate(float ck, float sk, const vec &axis)
- {
- matrix3 m;
- m.rotate(ck, sk, axis);
- *this = matrix4x3(m, vec(0, 0, 0));
- }
-
- void rotate_around_x(float ck, float sk)
- {
- vec rb = vec(b).mul(ck).madd(c, sk),
- rc = vec(c).mul(ck).msub(b, sk);
- b = rb;
- c = rc;
- }
- void rotate_around_x(float angle) { rotate_around_x(cosf(angle), sinf(angle)); }
- void rotate_around_x(const vec2 &sc) { rotate_around_x(sc.x, sc.y); }
-
- void rotate_around_y(float ck, float sk)
- {
- vec rc = vec(c).mul(ck).madd(a, sk),
- ra = vec(a).mul(ck).msub(c, sk);
- c = rc;
- a = ra;
- }
- void rotate_around_y(float angle) { rotate_around_y(cosf(angle), sinf(angle)); }
- void rotate_around_y(const vec2 &sc) { rotate_around_y(sc.x, sc.y); }
-
- void rotate_around_z(float ck, float sk)
- {
- vec ra = vec(a).mul(ck).madd(b, sk),
- rb = vec(b).mul(ck).msub(a, sk);
- a = ra;
- b = rb;
- }
- void rotate_around_z(float angle) { rotate_around_z(cosf(angle), sinf(angle)); }
- void rotate_around_z(const vec2 &sc) { rotate_around_z(sc.x, sc.y); }
-
- vec transform(const vec &o) const { return vec(d).madd(a, o.x).madd(b, o.y).madd(c, o.z); }
- vec transposedtransform(const vec &o) const { vec p = vec(o).sub(d); return vec(a.dot(p), b.dot(p), c.dot(p)); }
- vec transformnormal(const vec &o) const { return vec(a).mul(o.x).madd(b, o.y).madd(c, o.z); }
- vec transposedtransformnormal(const vec &o) const { return vec(a.dot(o), b.dot(o), c.dot(o)); }
- vec transform(const vec2 &o) const { return vec(d).madd(a, o.x).madd(b, o.y); }
-
- vec4 rowx() const { return vec4(a.x, b.x, c.x, d.x); }
- vec4 rowy() const { return vec4(a.y, b.y, c.y, d.y); }
- vec4 rowz() const { return vec4(a.z, b.z, c.z, d.z); }
+ vec a, b, c, d;
+
+ matrix4x3() {}
+ matrix4x3(const vec &a, const vec &b, const vec &c, const vec &d) : a(a), b(b), c(c), d(d) {}
+ matrix4x3(const matrix3 &rot, const vec &trans) : a(rot.a), b(rot.b), c(rot.c), d(trans) {}
+ matrix4x3(const dualquat &dq)
+ {
+ vec4 r = vec4(dq.real).mul(1/dq.real.squaredlen()), rr = vec4(r).mul(dq.real);
+ r.mul(2);
+ float xy = r.x*dq.real.y, xz = r.x*dq.real.z, yz = r.y*dq.real.z,
+ wx = r.w*dq.real.x, wy = r.w*dq.real.y, wz = r.w*dq.real.z;
+ a = vec(rr.w + rr.x - rr.y - rr.z, xy + wz, xz - wy);
+ b = vec(xy - wz, rr.w + rr.y - rr.x - rr.z, yz + wx);
+ c = vec(xz + wy, yz - wx, rr.w + rr.z - rr.x - rr.y);
+ d = vec(-(dq.dual.w*r.x - dq.dual.x*r.w + dq.dual.y*r.z - dq.dual.z*r.y),
+ -(dq.dual.w*r.y - dq.dual.x*r.z - dq.dual.y*r.w + dq.dual.z*r.x),
+ -(dq.dual.w*r.z + dq.dual.x*r.y - dq.dual.y*r.x - dq.dual.z*r.w));
+
+ }
+ explicit matrix4x3(const matrix4 &m);
+
+ void mul(float k)
+ {
+ a.mul(k);
+ b.mul(k);
+ c.mul(k);
+ d.mul(k);
+ }
+
+ void setscale(float x, float y, float z) { a.x = x; b.y = y; c.z = z; }
+ void setscale(const vec &v) { setscale(v.x, v.y, v.z); }
+ void setscale(float n) { setscale(n, n, n); }
+
+ void scale(float x, float y, float z)
+ {
+ a.mul(x);
+ b.mul(y);
+ c.mul(z);
+ }
+ void scale(const vec &v) { scale(v.x, v.y, v.z); }
+ void scale(float n) { scale(n, n, n); }
+
+ void settranslation(const vec &p) { d = p; }
+ void settranslation(float x, float y, float z) { d = vec(x, y, z); }
+
+ void translate(const vec &p) { d.madd(a, p.x).madd(b, p.y).madd(c, p.z); }
+ void translate(float x, float y, float z) { translate(vec(x, y, z)); }
+ void translate(const vec &p, float scale) { translate(vec(p).mul(scale)); }
+
+ void posttranslate(const vec &p) { d.add(p); }
+ void posttranslate(float x, float y, float z) { posttranslate(vec(x, y, z)); }
+ void posttranslate(const vec &p, float scale) { d.madd(p, scale); }
+
+ void accumulate(const matrix4x3 &m, float k)
+ {
+ a.madd(m.a, k);
+ b.madd(m.b, k);
+ c.madd(m.c, k);
+ d.madd(m.d, k);
+ }
+
+ void normalize()
+ {
+ a.normalize();
+ b.normalize();
+ c.normalize();
+ }
+
+ void lerp(const matrix4x3 &to, float t)
+ {
+ a.lerp(to.a, t);
+ b.lerp(to.b, t);
+ c.lerp(to.c, t);
+ d.lerp(to.d, t);
+ }
+ void lerp(const matrix4x3 &from, const matrix4x3 &to, float t)
+ {
+ a.lerp(from.a, to.a, t);
+ b.lerp(from.b, to.b, t);
+ c.lerp(from.c, to.c, t);
+ d.lerp(from.d, to.d, t);
+ }
+
+ void identity()
+ {
+ a = vec(1, 0, 0);
+ b = vec(0, 1, 0);
+ c = vec(0, 0, 1);
+ d = vec(0, 0, 0);
+ }
+
+ void mul(const matrix4x3 &m, const matrix4x3 &n)
+ {
+ a = vec(m.a).mul(n.a.x).madd(m.b, n.a.y).madd(m.c, n.a.z);
+ b = vec(m.a).mul(n.b.x).madd(m.b, n.b.y).madd(m.c, n.b.z);
+ c = vec(m.a).mul(n.c.x).madd(m.b, n.c.y).madd(m.c, n.c.z);
+ d = vec(m.d).madd(m.a, n.d.x).madd(m.b, n.d.y).madd(m.c, n.d.z);
+ }
+ void mul(const matrix4x3 &n) { mul(matrix4x3(*this), n); }
+
+ void mul(const matrix3 &m, const matrix4x3 &n)
+ {
+ a = vec(m.a).mul(n.a.x).madd(m.b, n.a.y).madd(m.c, n.a.z);
+ b = vec(m.a).mul(n.b.x).madd(m.b, n.b.y).madd(m.c, n.b.z);
+ c = vec(m.a).mul(n.c.x).madd(m.b, n.c.y).madd(m.c, n.c.z);
+ d = vec(m.a).mul(n.d.x).madd(m.b, n.d.y).madd(m.c, n.d.z);
+ }
+
+ void mul(const matrix3 &rot, const vec &trans, const matrix4x3 &n)
+ {
+ mul(rot, n);
+ d.add(trans);
+ }
+
+ void transpose()
+ {
+ d = vec(a.dot(d), b.dot(d), c.dot(d)).neg();
+ swap(a.y, b.x); swap(a.z, c.x);
+ swap(b.z, c.y);
+ }
+
+ void transpose(const matrix4x3 &o)
+ {
+ a = vec(o.a.x, o.b.x, o.c.x);
+ b = vec(o.a.y, o.b.y, o.c.y);
+ c = vec(o.a.z, o.b.z, o.c.z);
+ d = vec(o.a.dot(o.d), o.b.dot(o.d), o.c.dot(o.d)).neg();
+ }
+
+ void transposemul(const matrix4x3 &m, const matrix4x3 &n)
+ {
+ vec t(m.a.dot(m.d), m.b.dot(m.d), m.c.dot(m.d));
+ a = vec(m.a.dot(n.a), m.b.dot(n.a), m.c.dot(n.a));
+ b = vec(m.a.dot(n.b), m.b.dot(n.b), m.c.dot(n.b));
+ c = vec(m.a.dot(n.c), m.b.dot(n.c), m.c.dot(n.c));
+ d = vec(m.a.dot(n.d), m.b.dot(n.d), m.c.dot(n.d)).sub(t);
+ }
+
+ void multranspose(const matrix4x3 &m, const matrix4x3 &n)
+ {
+ vec t(n.a.dot(n.d), n.b.dot(n.d), n.c.dot(n.d));
+ a = vec(m.a).mul(n.a.x).madd(m.b, n.b.x).madd(m.c, n.c.x);
+ b = vec(m.a).mul(n.a.y).madd(m.b, n.b.y).madd(m.c, n.c.y);
+ c = vec(m.a).mul(n.a.z).madd(m.b, n.b.z).madd(m.c, n.c.z);
+ d = vec(m.d).msub(m.a, t.x).msub(m.b, t.y).msub(m.c, t.z);
+ }
+
+ void invert(const matrix4x3 &o)
+ {
+ vec unscale(1/o.a.squaredlen(), 1/o.b.squaredlen(), 1/o.c.squaredlen());
+ transpose(o);
+ a.mul(unscale);
+ b.mul(unscale);
+ c.mul(unscale);
+ d.mul(unscale);
+ }
+ void invert() { invert(matrix4x3(*this)); }
+
+ void rotate(float angle, const vec &d)
+ {
+ rotate(cosf(angle), sinf(angle), d);
+ }
+
+ void rotate(float ck, float sk, const vec &axis)
+ {
+ matrix3 m;
+ m.rotate(ck, sk, axis);
+ *this = matrix4x3(m, vec(0, 0, 0));
+ }
+
+ void rotate_around_x(float ck, float sk)
+ {
+ vec rb = vec(b).mul(ck).madd(c, sk),
+ rc = vec(c).mul(ck).msub(b, sk);
+ b = rb;
+ c = rc;
+ }
+ void rotate_around_x(float angle) { rotate_around_x(cosf(angle), sinf(angle)); }
+ void rotate_around_x(const vec2 &sc) { rotate_around_x(sc.x, sc.y); }
+
+ void rotate_around_y(float ck, float sk)
+ {
+ vec rc = vec(c).mul(ck).madd(a, sk),
+ ra = vec(a).mul(ck).msub(c, sk);
+ c = rc;
+ a = ra;
+ }
+ void rotate_around_y(float angle) { rotate_around_y(cosf(angle), sinf(angle)); }
+ void rotate_around_y(const vec2 &sc) { rotate_around_y(sc.x, sc.y); }
+
+ void rotate_around_z(float ck, float sk)
+ {
+ vec ra = vec(a).mul(ck).madd(b, sk),
+ rb = vec(b).mul(ck).msub(a, sk);
+ a = ra;
+ b = rb;
+ }
+ void rotate_around_z(float angle) { rotate_around_z(cosf(angle), sinf(angle)); }
+ void rotate_around_z(const vec2 &sc) { rotate_around_z(sc.x, sc.y); }
+
+ vec transform(const vec &o) const { return vec(d).madd(a, o.x).madd(b, o.y).madd(c, o.z); }
+ vec transposedtransform(const vec &o) const { vec p = vec(o).sub(d); return vec(a.dot(p), b.dot(p), c.dot(p)); }
+ vec transformnormal(const vec &o) const { return vec(a).mul(o.x).madd(b, o.y).madd(c, o.z); }
+ vec transposedtransformnormal(const vec &o) const { return vec(a.dot(o), b.dot(o), c.dot(o)); }
+ vec transform(const vec2 &o) const { return vec(d).madd(a, o.x).madd(b, o.y); }
+
+ vec4 rowx() const { return vec4(a.x, b.x, c.x, d.x); }
+ vec4 rowy() const { return vec4(a.y, b.y, c.y, d.y); }
+ vec4 rowz() const { return vec4(a.z, b.z, c.z, d.z); }
};
inline dualquat::dualquat(const matrix4x3 &m) : real(m)
{
- dual.x = 0.5f*( m.d.x*real.w + m.d.y*real.z - m.d.z*real.y);
- dual.y = 0.5f*(-m.d.x*real.z + m.d.y*real.w + m.d.z*real.x);
- dual.z = 0.5f*( m.d.x*real.y - m.d.y*real.x + m.d.z*real.w);
- dual.w = -0.5f*( m.d.x*real.x + m.d.y*real.y + m.d.z*real.z);
+ dual.x = 0.5f*( m.d.x*real.w + m.d.y*real.z - m.d.z*real.y);
+ dual.y = 0.5f*(-m.d.x*real.z + m.d.y*real.w + m.d.z*real.x);
+ dual.z = 0.5f*( m.d.x*real.y - m.d.y*real.x + m.d.z*real.w);
+ dual.w = -0.5f*( m.d.x*real.x + m.d.y*real.y + m.d.z*real.z);
}
inline matrix3::matrix3(const matrix4x3 &m) : a(m.a), b(m.b), c(m.c) {}
struct plane : vec
{
- float offset;
-
- float dist(const vec &p) const { return dot(p)+offset; }
- float dist(const vec4 &p) const { return p.dot3(*this) + p.w*offset; }
- bool operator==(const plane &p) const { return x==p.x && y==p.y && z==p.z && offset==p.offset; }
- bool operator!=(const plane &p) const { return x!=p.x || y!=p.y || z!=p.z || offset!=p.offset; }
-
- plane() {}
- plane(const vec &c, float off) : vec(c), offset(off) {}
- plane(const vec4 &p) : vec(p), offset(p.w) {}
- plane(int d, float off)
- {
- x = y = z = 0.0f;
- v[d] = 1.0f;
- offset = -off;
- }
- plane(float a, float b, float c, float d) : vec(a, b, c), offset(d) {}
-
- void toplane(const vec &n, const vec &p)
- {
- x = n.x; y = n.y; z = n.z;
- offset = -dot(p);
- }
-
- bool toplane(const vec &a, const vec &b, const vec &c)
- {
- cross(vec(b).sub(a), vec(c).sub(a));
- float mag = magnitude();
- if(!mag) return false;
- div(mag);
- offset = -dot(a);
- return true;
- }
-
- bool rayintersect(const vec &o, const vec &ray, float &dist)
- {
- float cosalpha = dot(ray);
- if(cosalpha==0) return false;
- float deltac = offset+dot(o);
- dist -= deltac/cosalpha;
- return true;
- }
-
- plane &reflectz(float rz)
- {
- offset += 2*rz*z;
- z = -z;
- return *this;
- }
-
- plane &invert()
- {
- neg();
- offset = -offset;
- return *this;
- }
-
- plane &scale(float k)
- {
- mul(k);
- return *this;
- }
-
- plane &translate(const vec &p)
- {
- offset += dot(p);
- return *this;
- }
-
- plane &normalize()
- {
- float mag = magnitude();
- div(mag);
- offset /= mag;
- return *this;
- }
-
- float zintersect(const vec &p) const { return -(x*p.x+y*p.y+offset)/z; }
- float zdelta(const vec &p) const { return -(x*p.x+y*p.y)/z; }
- float zdist(const vec &p) const { return p.z-zintersect(p); }
+ float offset;
+
+ float dist(const vec &p) const { return dot(p)+offset; }
+ float dist(const vec4 &p) const { return p.dot3(*this) + p.w*offset; }
+ bool operator==(const plane &p) const { return x==p.x && y==p.y && z==p.z && offset==p.offset; }
+ bool operator!=(const plane &p) const { return x!=p.x || y!=p.y || z!=p.z || offset!=p.offset; }
+
+ plane() {}
+ plane(const vec &c, float off) : vec(c), offset(off) {}
+ plane(const vec4 &p) : vec(p), offset(p.w) {}
+ plane(int d, float off)
+ {
+ x = y = z = 0.0f;
+ v[d] = 1.0f;
+ offset = -off;
+ }
+ plane(float a, float b, float c, float d) : vec(a, b, c), offset(d) {}
+
+ void toplane(const vec &n, const vec &p)
+ {
+ x = n.x; y = n.y; z = n.z;
+ offset = -dot(p);
+ }
+
+ bool toplane(const vec &a, const vec &b, const vec &c)
+ {
+ cross(vec(b).sub(a), vec(c).sub(a));
+ float mag = magnitude();
+ if(!mag) return false;
+ div(mag);
+ offset = -dot(a);
+ return true;
+ }
+
+ bool rayintersect(const vec &o, const vec &ray, float &dist)
+ {
+ float cosalpha = dot(ray);
+ if(cosalpha==0) return false;
+ float deltac = offset+dot(o);
+ dist -= deltac/cosalpha;
+ return true;
+ }
+
+ plane &reflectz(float rz)
+ {
+ offset += 2*rz*z;
+ z = -z;
+ return *this;
+ }
+
+ plane &invert()
+ {
+ neg();
+ offset = -offset;
+ return *this;
+ }
+
+ plane &scale(float k)
+ {
+ mul(k);
+ return *this;
+ }
+
+ plane &translate(const vec &p)
+ {
+ offset += dot(p);
+ return *this;
+ }
+
+ plane &normalize()
+ {
+ float mag = magnitude();
+ div(mag);
+ offset /= mag;
+ return *this;
+ }
+
+ float zintersect(const vec &p) const { return -(x*p.x+y*p.y+offset)/z; }
+ float zdelta(const vec &p) const { return -(x*p.x+y*p.y)/z; }
+ float zdist(const vec &p) const { return p.z-zintersect(p); }
};
struct triangle
{
- vec a, b, c;
+ vec a, b, c;
- triangle(const vec &a, const vec &b, const vec &c) : a(a), b(b), c(c) {}
- triangle() {}
+ triangle(const vec &a, const vec &b, const vec &c) : a(a), b(b), c(c) {}
+ triangle() {}
- triangle &add(const vec &o) { a.add(o); b.add(o); c.add(o); return *this; }
- triangle &sub(const vec &o) { a.sub(o); b.sub(o); c.sub(o); return *this; }
+ triangle &add(const vec &o) { a.add(o); b.add(o); c.add(o); return *this; }
+ triangle &sub(const vec &o) { a.sub(o); b.sub(o); c.sub(o); return *this; }
- bool operator==(const triangle &t) const { return a == t.a && b == t.b && c == t.c; }
+ bool operator==(const triangle &t) const { return a == t.a && b == t.b && c == t.c; }
};
/**
@@ -1133,680 +1133,680 @@ struct svec;
struct ivec
{
- union
- {
- struct { int x, y, z; };
- struct { int r, g, b; };
- int v[3];
- };
-
- ivec() {}
- explicit ivec(const vec &v) : x(int(v.x)), y(int(v.y)), z(int(v.z)) {}
- ivec(int a, int b, int c) : x(a), y(b), z(c) {}
- ivec(int d, int row, int col, int depth)
- {
- v[R[d]] = row;
- v[C[d]] = col;
- v[D[d]] = depth;
- }
- ivec(int i, const ivec &co, int size) : x(co.x+((i&1)>>0)*size), y(co.y+((i&2)>>1)*size), z(co.z +((i&4)>>2)*size) {}
- explicit ivec(const ivec4 &v);
- explicit ivec(const ivec2 &v, int z = 0);
- explicit ivec(const usvec &v);
- explicit ivec(const svec &v);
-
- int &operator[](int i) { return v[i]; }
- int operator[](int i) const { return v[i]; }
-
- //int idx(int i) { return v[i]; }
- bool operator==(const ivec &v) const { return x==v.x && y==v.y && z==v.z; }
- bool operator!=(const ivec &v) const { return x!=v.x || y!=v.y || z!=v.z; }
- bool iszero() const { return x==0 && y==0 && z==0; }
- ivec &shl(int n) { x<<= n; y<<= n; z<<= n; return *this; }
- ivec &shr(int n) { x>>= n; y>>= n; z>>= n; return *this; }
- ivec &mul(int n) { x *= n; y *= n; z *= n; return *this; }
- ivec &div(int n) { x /= n; y /= n; z /= n; return *this; }
- ivec &add(int n) { x += n; y += n; z += n; return *this; }
- ivec &sub(int n) { x -= n; y -= n; z -= n; return *this; }
- ivec &mul(const ivec &v) { x *= v.x; y *= v.y; z *= v.z; return *this; }
- ivec &div(const ivec &v) { x /= v.x; y /= v.y; z /= v.z; return *this; }
- ivec &add(const ivec &v) { x += v.x; y += v.y; z += v.z; return *this; }
- ivec &sub(const ivec &v) { x -= v.x; y -= v.y; z -= v.z; return *this; }
- ivec &mask(int n) { x &= n; y &= n; z &= n; return *this; }
- ivec &neg() { return mul(-1); }
- ivec &min(const ivec &o) { x = ::min(x, o.x); y = ::min(y, o.y); z = ::min(z, o.z); return *this; }
- ivec &max(const ivec &o) { x = ::max(x, o.x); y = ::max(y, o.y); z = ::max(z, o.z); return *this; }
- ivec &min(int n) { x = ::min(x, n); y = ::min(y, n); z = ::min(z, n); return *this; }
- ivec &max(int n) { x = ::max(x, n); y = ::max(y, n); z = ::max(z, n); return *this; }
- ivec &abs() { x = ::abs(x); y = ::abs(y); z = ::abs(z); return *this; }
- ivec &clamp(int l, int h) { x = ::clamp(x, l, h); y = ::clamp(y, l, h); z = ::clamp(z, l, h); return *this; }
- ivec &cross(const ivec &a, const ivec &b) { x = a.y*b.z-a.z*b.y; y = a.z*b.x-a.x*b.z; z = a.x*b.y-a.y*b.x; return *this; }
- int dot(const ivec &o) const { return x*o.x + y*o.y + z*o.z; }
- float dist(const plane &p) const { return x*p.x + y*p.y + z*p.z + p.offset; }
-
- static inline ivec floor(const vec &o) { return ivec(int(::floor(o.x)), int(::floor(o.y)), int(::floor(o.z))); }
- static inline ivec ceil(const vec &o) { return ivec(int(::ceil(o.x)), int(::ceil(o.y)), int(::ceil(o.z))); }
+ union
+ {
+ struct { int x, y, z; };
+ struct { int r, g, b; };
+ int v[3];
+ };
+
+ ivec() {}
+ explicit ivec(const vec &v) : x(int(v.x)), y(int(v.y)), z(int(v.z)) {}
+ ivec(int a, int b, int c) : x(a), y(b), z(c) {}
+ ivec(int d, int row, int col, int depth)
+ {
+ v[R[d]] = row;
+ v[C[d]] = col;
+ v[D[d]] = depth;
+ }
+ ivec(int i, const ivec &co, int size) : x(co.x+((i&1)>>0)*size), y(co.y+((i&2)>>1)*size), z(co.z +((i&4)>>2)*size) {}
+ explicit ivec(const ivec4 &v);
+ explicit ivec(const ivec2 &v, int z = 0);
+ explicit ivec(const usvec &v);
+ explicit ivec(const svec &v);
+
+ int &operator[](int i) { return v[i]; }
+ int operator[](int i) const { return v[i]; }
+
+ //int idx(int i) { return v[i]; }
+ bool operator==(const ivec &v) const { return x==v.x && y==v.y && z==v.z; }
+ bool operator!=(const ivec &v) const { return x!=v.x || y!=v.y || z!=v.z; }
+ bool iszero() const { return x==0 && y==0 && z==0; }
+ ivec &shl(int n) { x<<= n; y<<= n; z<<= n; return *this; }
+ ivec &shr(int n) { x>>= n; y>>= n; z>>= n; return *this; }
+ ivec &mul(int n) { x *= n; y *= n; z *= n; return *this; }
+ ivec &div(int n) { x /= n; y /= n; z /= n; return *this; }
+ ivec &add(int n) { x += n; y += n; z += n; return *this; }
+ ivec &sub(int n) { x -= n; y -= n; z -= n; return *this; }
+ ivec &mul(const ivec &v) { x *= v.x; y *= v.y; z *= v.z; return *this; }
+ ivec &div(const ivec &v) { x /= v.x; y /= v.y; z /= v.z; return *this; }
+ ivec &add(const ivec &v) { x += v.x; y += v.y; z += v.z; return *this; }
+ ivec &sub(const ivec &v) { x -= v.x; y -= v.y; z -= v.z; return *this; }
+ ivec &mask(int n) { x &= n; y &= n; z &= n; return *this; }
+ ivec &neg() { return mul(-1); }
+ ivec &min(const ivec &o) { x = ::min(x, o.x); y = ::min(y, o.y); z = ::min(z, o.z); return *this; }
+ ivec &max(const ivec &o) { x = ::max(x, o.x); y = ::max(y, o.y); z = ::max(z, o.z); return *this; }
+ ivec &min(int n) { x = ::min(x, n); y = ::min(y, n); z = ::min(z, n); return *this; }
+ ivec &max(int n) { x = ::max(x, n); y = ::max(y, n); z = ::max(z, n); return *this; }
+ ivec &abs() { x = ::abs(x); y = ::abs(y); z = ::abs(z); return *this; }
+ ivec &clamp(int l, int h) { x = ::clamp(x, l, h); y = ::clamp(y, l, h); z = ::clamp(z, l, h); return *this; }
+ ivec &cross(const ivec &a, const ivec &b) { x = a.y*b.z-a.z*b.y; y = a.z*b.x-a.x*b.z; z = a.x*b.y-a.y*b.x; return *this; }
+ int dot(const ivec &o) const { return x*o.x + y*o.y + z*o.z; }
+ float dist(const plane &p) const { return x*p.x + y*p.y + z*p.z + p.offset; }
+
+ static inline ivec floor(const vec &o) { return ivec(int(::floor(o.x)), int(::floor(o.y)), int(::floor(o.z))); }
+ static inline ivec ceil(const vec &o) { return ivec(int(::ceil(o.x)), int(::ceil(o.y)), int(::ceil(o.z))); }
};
inline vec::vec(const ivec &v) : x(v.x), y(v.y), z(v.z) {}
static inline bool htcmp(const ivec &x, const ivec &y)
{
- return x == y;
-}
+ return x == y;
+}
static inline uint hthash(const ivec &k)
{
- return k.x^k.y^k.z;
-}
+ return k.x^k.y^k.z;
+}
struct ivec2
{
- union
- {
- struct { int x, y; };
- int v[2];
- };
-
- ivec2() {}
- ivec2(int x, int y) : x(x), y(y) {}
- explicit ivec2(const vec2 &v) : x(int(v.x)), y(int(v.y)) {}
- explicit ivec2(const ivec &v) : x(v.x), y(v.y) {}
-
- int &operator[](int i) { return v[i]; }
- int operator[](int i) const { return v[i]; }
-
- bool operator==(const ivec2 &o) const { return x == o.x && y == o.y; }
- bool operator!=(const ivec2 &o) const { return x != o.x || y != o.y; }
-
- bool iszero() const { return x==0 && y==0; }
- ivec2 &shl(int n) { x<<= n; y<<= n; return *this; }
- ivec2 &shr(int n) { x>>= n; y>>= n; return *this; }
- ivec2 &mul(int n) { x *= n; y *= n; return *this; }
- ivec2 &div(int n) { x /= n; y /= n; return *this; }
- ivec2 &add(int n) { x += n; y += n; return *this; }
- ivec2 &sub(int n) { x -= n; y -= n; return *this; }
- ivec2 &mul(const ivec2 &v) { x *= v.x; y *= v.y; return *this; }
- ivec2 &div(const ivec2 &v) { x /= v.x; y /= v.y; return *this; }
- ivec2 &add(const ivec2 &v) { x += v.x; y += v.y; return *this; }
- ivec2 &sub(const ivec2 &v) { x -= v.x; y -= v.y; return *this; }
- ivec2 &mask(int n) { x &= n; y &= n; return *this; }
- ivec2 &neg() { x = -x; y = -y; return *this; }
- ivec2 &min(const ivec2 &o) { x = ::min(x, o.x); y = ::min(y, o.y); return *this; }
- ivec2 &max(const ivec2 &o) { x = ::max(x, o.x); y = ::max(y, o.y); return *this; }
- ivec2 &min(int n) { x = ::min(x, n); y = ::min(y, n); return *this; }
- ivec2 &max(int n) { x = ::max(x, n); y = ::max(y, n); return *this; }
- ivec2 &abs() { x = ::abs(x); y = ::abs(y); return *this; }
- int dot(const ivec2 &o) const { return x*o.x + y*o.y; }
- int cross(const ivec2 &o) const { return x*o.y - y*o.x; }
+ union
+ {
+ struct { int x, y; };
+ int v[2];
+ };
+
+ ivec2() {}
+ ivec2(int x, int y) : x(x), y(y) {}
+ explicit ivec2(const vec2 &v) : x(int(v.x)), y(int(v.y)) {}
+ explicit ivec2(const ivec &v) : x(v.x), y(v.y) {}
+
+ int &operator[](int i) { return v[i]; }
+ int operator[](int i) const { return v[i]; }
+
+ bool operator==(const ivec2 &o) const { return x == o.x && y == o.y; }
+ bool operator!=(const ivec2 &o) const { return x != o.x || y != o.y; }
+
+ bool iszero() const { return x==0 && y==0; }
+ ivec2 &shl(int n) { x<<= n; y<<= n; return *this; }
+ ivec2 &shr(int n) { x>>= n; y>>= n; return *this; }
+ ivec2 &mul(int n) { x *= n; y *= n; return *this; }
+ ivec2 &div(int n) { x /= n; y /= n; return *this; }
+ ivec2 &add(int n) { x += n; y += n; return *this; }
+ ivec2 &sub(int n) { x -= n; y -= n; return *this; }
+ ivec2 &mul(const ivec2 &v) { x *= v.x; y *= v.y; return *this; }
+ ivec2 &div(const ivec2 &v) { x /= v.x; y /= v.y; return *this; }
+ ivec2 &add(const ivec2 &v) { x += v.x; y += v.y; return *this; }
+ ivec2 &sub(const ivec2 &v) { x -= v.x; y -= v.y; return *this; }
+ ivec2 &mask(int n) { x &= n; y &= n; return *this; }
+ ivec2 &neg() { x = -x; y = -y; return *this; }
+ ivec2 &min(const ivec2 &o) { x = ::min(x, o.x); y = ::min(y, o.y); return *this; }
+ ivec2 &max(const ivec2 &o) { x = ::max(x, o.x); y = ::max(y, o.y); return *this; }
+ ivec2 &min(int n) { x = ::min(x, n); y = ::min(y, n); return *this; }
+ ivec2 &max(int n) { x = ::max(x, n); y = ::max(y, n); return *this; }
+ ivec2 &abs() { x = ::abs(x); y = ::abs(y); return *this; }
+ int dot(const ivec2 &o) const { return x*o.x + y*o.y; }
+ int cross(const ivec2 &o) const { return x*o.y - y*o.x; }
};
inline ivec::ivec(const ivec2 &v, int z) : x(v.x), y(v.y), z(z) {}
static inline bool htcmp(const ivec2 &x, const ivec2 &y)
{
- return x == y;
+ return x == y;
}
static inline uint hthash(const ivec2 &k)
{
- return k.x^k.y;
+ return k.x^k.y;
}
struct ivec4
{
- union
- {
- struct { int x, y, z, w; };
- struct { int r, g, b, a; };
- int v[4];
- };
-
- ivec4() {}
- explicit ivec4(const ivec &p, int w = 0) : x(p.x), y(p.y), z(p.z), w(w) {}
- ivec4(int x, int y, int z, int w) : x(x), y(y), z(z), w(w) {}
- explicit ivec4(const vec4 &v) : x(int(v.x)), y(int(v.y)), z(int(v.z)), w(int(v.w)) {}
-
- bool operator==(const ivec4 &o) const { return x == o.x && y == o.y && z == o.z && w == o.w; }
- bool operator!=(const ivec4 &o) const { return x != o.x || y != o.y || z != o.z || w != o.w; }
+ union
+ {
+ struct { int x, y, z, w; };
+ struct { int r, g, b, a; };
+ int v[4];
+ };
+
+ ivec4() {}
+ explicit ivec4(const ivec &p, int w = 0) : x(p.x), y(p.y), z(p.z), w(w) {}
+ ivec4(int x, int y, int z, int w) : x(x), y(y), z(z), w(w) {}
+ explicit ivec4(const vec4 &v) : x(int(v.x)), y(int(v.y)), z(int(v.z)), w(int(v.w)) {}
+
+ bool operator==(const ivec4 &o) const { return x == o.x && y == o.y && z == o.z && w == o.w; }
+ bool operator!=(const ivec4 &o) const { return x != o.x || y != o.y || z != o.z || w != o.w; }
};
inline ivec::ivec(const ivec4 &v) : x(v.x), y(v.y), z(v.z) {}
static inline bool htcmp(const ivec4 &x, const ivec4 &y)
{
- return x == y;
+ return x == y;
}
static inline uint hthash(const ivec4 &k)
{
- return k.x^k.y^k.z^k.w;
+ return k.x^k.y^k.z^k.w;
}
struct bvec4;
struct bvec
{
- union
- {
- struct { uchar x, y, z; };
- struct { uchar r, g, b; };
- uchar v[3];
- };
+ union
+ {
+ struct { uchar x, y, z; };
+ struct { uchar r, g, b; };
+ uchar v[3];
+ };
- bvec() {}
- bvec(uchar x, uchar y, uchar z) : x(x), y(y), z(z) {}
- explicit bvec(const vec &v) : x(uchar((v.x+1)*(255.0f/2.0f))), y(uchar((v.y+1)*(255.0f/2.0f))), z(uchar((v.z+1)*(255.0f/2.0f))) {}
- explicit bvec(const bvec4 &v);
+ bvec() {}
+ bvec(uchar x, uchar y, uchar z) : x(x), y(y), z(z) {}
+ explicit bvec(const vec &v) : x(uchar((v.x+1)*(255.0f/2.0f))), y(uchar((v.y+1)*(255.0f/2.0f))), z(uchar((v.z+1)*(255.0f/2.0f))) {}
+ explicit bvec(const bvec4 &v);
- uchar &operator[](int i) { return v[i]; }
- uchar operator[](int i) const { return v[i]; }
+ uchar &operator[](int i) { return v[i]; }
+ uchar operator[](int i) const { return v[i]; }
- bool operator==(const bvec &v) const { return x==v.x && y==v.y && z==v.z; }
- bool operator!=(const bvec &v) const { return x!=v.x || y!=v.y || z!=v.z; }
+ bool operator==(const bvec &v) const { return x==v.x && y==v.y && z==v.z; }
+ bool operator!=(const bvec &v) const { return x!=v.x || y!=v.y || z!=v.z; }
- bool iszero() const { return x==0 && y==0 && z==0; }
+ bool iszero() const { return x==0 && y==0 && z==0; }
- vec tonormal() const { return vec(x*(2.0f/255.0f)-1.0f, y*(2.0f/255.0f)-1.0f, z*(2.0f/255.0f)-1.0f); }
+ vec tonormal() const { return vec(x*(2.0f/255.0f)-1.0f, y*(2.0f/255.0f)-1.0f, z*(2.0f/255.0f)-1.0f); }
- bvec &normalize()
- {
- vec n(x-127.5f, y-127.5f, z-127.5f);
- float mag = 127.5f/n.magnitude();
- x = uchar(n.x*mag+127.5f);
- y = uchar(n.y*mag+127.5f);
- z = uchar(n.z*mag+127.5f);
- return *this;
- }
+ bvec &normalize()
+ {
+ vec n(x-127.5f, y-127.5f, z-127.5f);
+ float mag = 127.5f/n.magnitude();
+ x = uchar(n.x*mag+127.5f);
+ y = uchar(n.y*mag+127.5f);
+ z = uchar(n.z*mag+127.5f);
+ return *this;
+ }
- void lerp(const bvec &a, const bvec &b, float t) { x = uchar(a.x + (b.x-a.x)*t); y = uchar(a.y + (b.y-a.y)*t); z = uchar(a.z + (b.z-a.z)*t); }
+ void lerp(const bvec &a, const bvec &b, float t) { x = uchar(a.x + (b.x-a.x)*t); y = uchar(a.y + (b.y-a.y)*t); z = uchar(a.z + (b.z-a.z)*t); }
- void lerp(const bvec &a, const bvec &b, int ka, int kb, int d)
- {
- x = uchar((a.x*ka + b.x*kb)/d);
- y = uchar((a.y*ka + b.y*kb)/d);
- z = uchar((a.z*ka + b.z*kb)/d);
- }
+ void lerp(const bvec &a, const bvec &b, int ka, int kb, int d)
+ {
+ x = uchar((a.x*ka + b.x*kb)/d);
+ y = uchar((a.y*ka + b.y*kb)/d);
+ z = uchar((a.z*ka + b.z*kb)/d);
+ }
- void flip() { x ^= 0x80; y ^= 0x80; z ^= 0x80; }
+ void flip() { x ^= 0x80; y ^= 0x80; z ^= 0x80; }
- void scale(int k, int d) { x = uchar((x*k)/d); y = uchar((y*k)/d); z = uchar((z*k)/d); }
+ void scale(int k, int d) { x = uchar((x*k)/d); y = uchar((y*k)/d); z = uchar((z*k)/d); }
- bvec &shl(int n) { x<<= n; y<<= n; z<<= n; return *this; }
- bvec &shr(int n) { x>>= n; y>>= n; z>>= n; return *this; }
+ bvec &shl(int n) { x<<= n; y<<= n; z<<= n; return *this; }
+ bvec &shr(int n) { x>>= n; y>>= n; z>>= n; return *this; }
- static bvec fromcolor(const vec &v) { return bvec(uchar(v.x*255.0f), uchar(v.y*255.0f), uchar(v.z*255.0f)); }
- vec tocolor() const { return vec(x*(1.0f/255.0f), y*(1.0f/255.0f), z*(1.0f/255.0f)); }
+ static bvec fromcolor(const vec &v) { return bvec(uchar(v.x*255.0f), uchar(v.y*255.0f), uchar(v.z*255.0f)); }
+ vec tocolor() const { return vec(x*(1.0f/255.0f), y*(1.0f/255.0f), z*(1.0f/255.0f)); }
- static bvec from565(ushort c) { return bvec((((c>>11)&0x1F)*527 + 15) >> 6, (((c>>5)&0x3F)*259 + 35) >> 6, ((c&0x1F)*527 + 15) >> 6); }
+ static bvec from565(ushort c) { return bvec((((c>>11)&0x1F)*527 + 15) >> 6, (((c>>5)&0x3F)*259 + 35) >> 6, ((c&0x1F)*527 + 15) >> 6); }
- static bvec hexcolor(int color)
- {
- return bvec((color>>16)&0xFF, (color>>8)&0xFF, color&0xFF);
- }
- int tohexcolor() const { return (int(r)<<16)|(int(g)<<8)|int(b); }
+ static bvec hexcolor(int color)
+ {
+ return bvec((color>>16)&0xFF, (color>>8)&0xFF, color&0xFF);
+ }
+ int tohexcolor() const { return (int(r)<<16)|(int(g)<<8)|int(b); }
};
struct bvec4
{
- union
- {
- struct { uchar x, y, z, w; };
- struct { uchar r, g, b, a; };
- uchar v[4];
- uint mask;
- };
-
- bvec4() {}
- bvec4(uchar x, uchar y, uchar z, uchar w = 0) : x(x), y(y), z(z), w(w) {}
- bvec4(const bvec &v, uchar w = 0) : x(v.x), y(v.y), z(v.z), w(w) {}
-
- uchar &operator[](int i) { return v[i]; }
- uchar operator[](int i) const { return v[i]; }
-
- bool operator==(const bvec4 &v) const { return mask==v.mask; }
- bool operator!=(const bvec4 &v) const { return mask!=v.mask; }
-
- bool iszero() const { return mask==0; }
-
- vec tonormal() const { return vec(x*(2.0f/255.0f)-1.0f, y*(2.0f/255.0f)-1.0f, z*(2.0f/255.0f)-1.0f); }
-
- void lerp(const bvec4 &a, const bvec4 &b, float t)
- {
- x = uchar(a.x + (b.x-a.x)*t);
- y = uchar(a.y + (b.y-a.y)*t);
- z = uchar(a.z + (b.z-a.z)*t);
- w = a.w;
- }
-
- void lerp(const bvec4 &a, const bvec4 &b, int ka, int kb, int d)
- {
- x = uchar((a.x*ka + b.x*kb)/d);
- y = uchar((a.y*ka + b.y*kb)/d);
- z = uchar((a.z*ka + b.z*kb)/d);
- w = a.w;
- }
-
- void flip() { mask ^= 0x80808080; }
+ union
+ {
+ struct { uchar x, y, z, w; };
+ struct { uchar r, g, b, a; };
+ uchar v[4];
+ uint mask;
+ };
+
+ bvec4() {}
+ bvec4(uchar x, uchar y, uchar z, uchar w = 0) : x(x), y(y), z(z), w(w) {}
+ bvec4(const bvec &v, uchar w = 0) : x(v.x), y(v.y), z(v.z), w(w) {}
+
+ uchar &operator[](int i) { return v[i]; }
+ uchar operator[](int i) const { return v[i]; }
+
+ bool operator==(const bvec4 &v) const { return mask==v.mask; }
+ bool operator!=(const bvec4 &v) const { return mask!=v.mask; }
+
+ bool iszero() const { return mask==0; }
+
+ vec tonormal() const { return vec(x*(2.0f/255.0f)-1.0f, y*(2.0f/255.0f)-1.0f, z*(2.0f/255.0f)-1.0f); }
+
+ void lerp(const bvec4 &a, const bvec4 &b, float t)
+ {
+ x = uchar(a.x + (b.x-a.x)*t);
+ y = uchar(a.y + (b.y-a.y)*t);
+ z = uchar(a.z + (b.z-a.z)*t);
+ w = a.w;
+ }
+
+ void lerp(const bvec4 &a, const bvec4 &b, int ka, int kb, int d)
+ {
+ x = uchar((a.x*ka + b.x*kb)/d);
+ y = uchar((a.y*ka + b.y*kb)/d);
+ z = uchar((a.z*ka + b.z*kb)/d);
+ w = a.w;
+ }
+
+ void flip() { mask ^= 0x80808080; }
};
inline bvec::bvec(const bvec4 &v) : x(v.x), y(v.y), z(v.z) {}
struct usvec
{
- union
- {
- struct { ushort x, y, z; };
- ushort v[3];
- };
-
- ushort &operator[](int i) { return v[i]; }
- ushort operator[](int i) const { return v[i]; }
+ union
+ {
+ struct { ushort x, y, z; };
+ ushort v[3];
+ };
+
+ ushort &operator[](int i) { return v[i]; }
+ ushort operator[](int i) const { return v[i]; }
};
inline ivec::ivec(const usvec &v) : x(v.x), y(v.y), z(v.z) {}
struct svec
{
- union
- {
- struct { short x, y, z; };
- short v[3];
- };
-
- svec() {}
- svec(short x, short y, short z) : x(x), y(y), z(z) {}
- explicit svec(const ivec &v) : x(v.x), y(v.y), z(v.z) {}
-
- short &operator[](int i) { return v[i]; }
- short operator[](int i) const { return v[i]; }
+ union
+ {
+ struct { short x, y, z; };
+ short v[3];
+ };
+
+ svec() {}
+ svec(short x, short y, short z) : x(x), y(y), z(z) {}
+ explicit svec(const ivec &v) : x(v.x), y(v.y), z(v.z) {}
+
+ short &operator[](int i) { return v[i]; }
+ short operator[](int i) const { return v[i]; }
};
inline ivec::ivec(const svec &v) : x(v.x), y(v.y), z(v.z) {}
struct svec2
{
- union
- {
- struct { short x, y; };
- short v[2];
- };
+ union
+ {
+ struct { short x, y; };
+ short v[2];
+ };
- svec2() {}
- svec2(short x, short y) : x(x), y(y) {}
+ svec2() {}
+ svec2(short x, short y) : x(x), y(y) {}
- short &operator[](int i) { return v[i]; }
- short operator[](int i) const { return v[i]; }
+ short &operator[](int i) { return v[i]; }
+ short operator[](int i) const { return v[i]; }
- bool operator==(const svec2 &o) const { return x == o.x && y == o.y; }
- bool operator!=(const svec2 &o) const { return x != o.x || y != o.y; }
+ bool operator==(const svec2 &o) const { return x == o.x && y == o.y; }
+ bool operator!=(const svec2 &o) const { return x != o.x || y != o.y; }
- bool iszero() const { return x==0 && y==0; }
+ bool iszero() const { return x==0 && y==0; }
};
struct dvec4
{
- double x, y, z, w;
+ double x, y, z, w;
- dvec4() {}
- dvec4(double x, double y, double z, double w) : x(x), y(y), z(z), w(w) {}
- dvec4(const vec4 &v) : x(v.x), y(v.y), z(v.z), w(v.w) {}
+ dvec4() {}
+ dvec4(double x, double y, double z, double w) : x(x), y(y), z(z), w(w) {}
+ dvec4(const vec4 &v) : x(v.x), y(v.y), z(v.z), w(v.w) {}
- template<class B> dvec4 &madd(const dvec4 &a, const B &b) { return add(dvec4(a).mul(b)); }
- dvec4 &mul(double f) { x *= f; y *= f; z *= f; w *= f; return *this; }
- dvec4 &mul(const dvec4 &o) { x *= o.x; y *= o.y; z *= o.z; w *= o.w; return *this; }
- dvec4 &add(double f) { x += f; y += f; z += f; w += f; return *this; }
- dvec4 &add(const dvec4 &o) { x += o.x; y += o.y; z += o.z; w += o.w; return *this; }
+ template<class B> dvec4 &madd(const dvec4 &a, const B &b) { return add(dvec4(a).mul(b)); }
+ dvec4 &mul(double f) { x *= f; y *= f; z *= f; w *= f; return *this; }
+ dvec4 &mul(const dvec4 &o) { x *= o.x; y *= o.y; z *= o.z; w *= o.w; return *this; }
+ dvec4 &add(double f) { x += f; y += f; z += f; w += f; return *this; }
+ dvec4 &add(const dvec4 &o) { x += o.x; y += o.y; z += o.z; w += o.w; return *this; }
- operator vec4() const { return vec4(x, y, z, w); }
+ operator vec4() const { return vec4(x, y, z, w); }
};
struct matrix4
{
- vec4 a, b, c, d;
-
- matrix4() {}
- matrix4(const float *m) : a(m), b(m+4), c(m+8), d(m+12) {}
- matrix4(const vec &a, const vec &b, const vec &c = vec(0, 0, 1))
- : a(a.x, b.x, c.x, 0), b(a.y, b.y, c.y, 0), c(a.z, b.z, c.z, 0), d(0, 0, 0, 1)
- {}
- matrix4(const vec4 &a, const vec4 &b, const vec4 &c, const vec4 &d = vec4(0, 0, 0, 1))
- : a(a), b(b), c(c), d(d)
- {}
- matrix4(const matrix4x3 &m)
- : a(m.a, 0), b(m.b, 0), c(m.c, 0), d(m.d, 1)
- {}
- matrix4(const matrix3 &rot, const vec &trans)
- : a(rot.a, 0), b(rot.b, 0), c(rot.c, 0), d(trans, 1)
- {}
-
- void mul(const matrix4 &x, const matrix3 &y)
- {
- a = vec4(x.a).mul(y.a.x).madd(x.b, y.a.y).madd(x.c, y.a.z);
- b = vec4(x.a).mul(y.b.x).madd(x.b, y.b.y).madd(x.c, y.b.z);
- c = vec4(x.a).mul(y.c.x).madd(x.b, y.c.y).madd(x.c, y.c.z);
- d = x.d;
- }
- void mul(const matrix3 &y) { mul(matrix4(*this), y); }
-
- template<class T> void mult(const matrix4 &x, const matrix4 &y)
- {
- a = T(x.a).mul(y.a.x).madd(x.b, y.a.y).madd(x.c, y.a.z).madd(x.d, y.a.w);
- b = T(x.a).mul(y.b.x).madd(x.b, y.b.y).madd(x.c, y.b.z).madd(x.d, y.b.w);
- c = T(x.a).mul(y.c.x).madd(x.b, y.c.y).madd(x.c, y.c.z).madd(x.d, y.c.w);
- d = T(x.a).mul(y.d.x).madd(x.b, y.d.y).madd(x.c, y.d.z).madd(x.d, y.d.w);
- }
-
- void mul(const matrix4 &x, const matrix4 &y) { mult<vec4>(x, y); }
- void mul(const matrix4 &y) { mult<vec4>(matrix4(*this), y); }
-
- void muld(const matrix4 &x, const matrix4 &y) { mult<dvec4>(x, y); }
- void muld(const matrix4 &y) { mult<dvec4>(matrix4(*this), y); }
-
- void rotate_around_x(float ck, float sk)
- {
- vec4 rb = vec4(b).mul(ck).madd(c, sk),
- rc = vec4(c).mul(ck).msub(b, sk);
- b = rb;
- c = rc;
- }
- void rotate_around_x(float angle) { rotate_around_x(cosf(angle), sinf(angle)); }
- void rotate_around_x(const vec2 &sc) { rotate_around_x(sc.x, sc.y); }
-
- void rotate_around_y(float ck, float sk)
- {
- vec4 rc = vec4(c).mul(ck).madd(a, sk),
- ra = vec4(a).mul(ck).msub(c, sk);
- c = rc;
- a = ra;
- }
- void rotate_around_y(float angle) { rotate_around_y(cosf(angle), sinf(angle)); }
- void rotate_around_y(const vec2 &sc) { rotate_around_y(sc.x, sc.y); }
-
- void rotate_around_z(float ck, float sk)
- {
- vec4 ra = vec4(a).mul(ck).madd(b, sk),
- rb = vec4(b).mul(ck).msub(a, sk);
- a = ra;
- b = rb;
- }
- void rotate_around_z(float angle) { rotate_around_z(cosf(angle), sinf(angle)); }
- void rotate_around_z(const vec2 &sc) { rotate_around_z(sc.x, sc.y); }
-
- void rotate(float ck, float sk, const vec &axis)
- {
- matrix3 m;
- m.rotate(ck, sk, axis);
- mul(m);
- }
- void rotate(float angle, const vec &dir) { rotate(cosf(angle), sinf(angle), dir); }
- void rotate(const vec2 &sc, const vec &dir) { rotate(sc.x, sc.y, dir); }
-
- void identity()
- {
- a = vec4(1, 0, 0, 0);
- b = vec4(0, 1, 0, 0);
- c = vec4(0, 0, 1, 0);
- d = vec4(0, 0, 0, 1);
- }
-
- void settranslation(const vec &v) { d.setxyz(v); }
- void settranslation(float x, float y, float z) { d.x = x; d.y = y; d.z = z; }
-
- void translate(const vec &p) { d.madd(a, p.x).madd(b, p.y).madd(c, p.z); }
- void translate(float x, float y, float z) { translate(vec(x, y, z)); }
- void translate(const vec &p, float scale) { translate(vec(p).mul(scale)); }
-
- void setscale(float x, float y, float z) { a.x = x; b.y = y; c.z = z; }
- void setscale(const vec &v) { setscale(v.x, v.y, v.z); }
- void setscale(float n) { setscale(n, n, n); }
-
- void scale(float x, float y, float z)
- {
- a.mul(x);
- b.mul(y);
- c.mul(z);
- }
- void scale(const vec &v) { scale(v.x, v.y, v.z); }
- void scale(float n) { scale(n, n, n); }
-
- void scalexy(float x, float y)
- {
- a.x *= x; a.y *= y;
- b.x *= x; b.y *= y;
- c.x *= x; c.y *= y;
- d.x *= x; d.y *= y;
- }
-
- void scalez(float k)
- {
- a.z *= k;
- b.z *= k;
- c.z *= k;
- d.z *= k;
- }
-
- void reflectz(float z)
- {
- d.add(vec4(c).mul(2*z));
- c.neg();
- }
-
- void projective(float zscale = 0.5f, float zoffset = 0.5f)
- {
- a.x = 0.5f*(a.x + a.w);
- a.y = 0.5f*(a.y + a.w);
- b.x = 0.5f*(b.x + b.w);
- b.y = 0.5f*(b.y + b.w);
- c.x = 0.5f*(c.x + c.w);
- c.y = 0.5f*(c.y + c.w);
- d.x = 0.5f*(d.x + d.w);
- d.y = 0.5f*(d.y + d.w);
- a.z = zscale*a.z + zoffset*a.w;
- b.z = zscale*b.z + zoffset*b.w;
- c.z = zscale*c.z + zoffset*c.w;
- d.z = zscale*d.z + zoffset*d.w;
- }
-
- void jitter(float x, float y)
- {
- a.x += x * a.w;
- a.y += y * a.w;
- b.x += x * b.w;
- b.y += y * b.w;
- c.x += x * c.w;
- c.y += y * c.w;
- d.x += x * d.w;
- d.y += y * d.w;
- }
-
- void transpose()
- {
- swap(a.y, b.x); swap(a.z, c.x); swap(a.w, d.x);
- swap(b.z, c.y); swap(b.w, d.y);
- swap(c.w, d.z);
- }
-
- void transpose(const matrix4 &m)
- {
- a = vec4(m.a.x, m.b.x, m.c.x, m.d.x);
- b = vec4(m.a.y, m.b.y, m.c.y, m.d.y);
- c = vec4(m.a.z, m.b.z, m.c.z, m.d.z);
- d = vec4(m.a.w, m.b.w, m.c.w, m.d.w);
- }
-
- void frustum(float left, float right, float bottom, float top, float znear, float zfar)
- {
- float width = right - left, height = top - bottom, zrange = znear - zfar;
- a = vec4(2*znear/width, 0, 0, 0);
- b = vec4(0, 2*znear/height, 0, 0);
- c = vec4((right + left)/width, (top + bottom)/height, (zfar + znear)/zrange, -1);
- d = vec4(0, 0, 2*znear*zfar/zrange, 0);
- }
-
- void perspective(float fovy, float aspect, float znear, float zfar)
- {
- float ydist = znear * tan(fovy/2*RAD), xdist = ydist * aspect;
- frustum(-xdist, xdist, -ydist, ydist, znear, zfar);
- }
-
- void ortho(float left, float right, float bottom, float top, float znear, float zfar)
- {
- float width = right - left, height = top - bottom, zrange = znear - zfar;
- a = vec4(2/width, 0, 0, 0);
- b = vec4(0, 2/height, 0, 0);
- c = vec4(0, 0, 2/zrange, 0);
- d = vec4(-(right+left)/width, -(top+bottom)/height, (zfar+znear)/zrange, 1);
- }
-
- void clip(const plane &p, const matrix4 &m)
- {
- float x = ((p.x<0 ? -1 : (p.x>0 ? 1 : 0)) + m.c.x) / m.a.x,
- y = ((p.y<0 ? -1 : (p.y>0 ? 1 : 0)) + m.c.y) / m.b.y,
- w = (1 + m.c.z) / m.d.z,
- scale = 2 / (x*p.x + y*p.y - p.z + w*p.offset);
- a = vec4(m.a.x, m.a.y, p.x*scale, m.a.w);
- b = vec4(m.b.x, m.b.y, p.y*scale, m.b.w);
- c = vec4(m.c.x, m.c.y, p.z*scale + 1.0f, m.c.w);
- d = vec4(m.d.x, m.d.y, p.offset*scale, m.d.w);
- }
-
- void transform(const vec &in, vec &out) const
- {
- out = vec(a).mul(in.x).add(vec(b).mul(in.y)).add(vec(c).mul(in.z)).add(vec(d));
- }
-
- void transform(const vec4 &in, vec &out) const
- {
- out = vec(a).mul(in.x).add(vec(b).mul(in.y)).add(vec(c).mul(in.z)).add(vec(d).mul(in.w));
- }
-
- void transform(const vec &in, vec4 &out) const
- {
- out = vec4(a).mul(in.x).madd(b, in.y).madd(c, in.z).add(d);
- }
-
- void transform(const vec4 &in, vec4 &out) const
- {
- out = vec4(a).mul(in.x).madd(b, in.y).madd(c, in.z).madd(d, in.w);
- }
-
- template<class T, class U> T transform(const U &in) const
- {
- T v;
- transform(in, v);
- return v;
- }
-
- template<class T> vec perspectivetransform(const T &in) const
- {
- vec4 v;
- transform(in, v);
- return vec(v).div(v.w);
- }
-
- void transformnormal(const vec &in, vec &out) const
- {
- out = vec(a).mul(in.x).add(vec(b).mul(in.y)).add(vec(c).mul(in.z));
- }
-
- void transformnormal(const vec &in, vec4 &out) const
- {
- out = vec4(a).mul(in.x).madd(b, in.y).madd(c, in.z);
- }
-
- template<class T, class U> T transformnormal(const U &in) const
- {
- T v;
- transformnormal(in, v);
- return v;
- }
-
- void transposedtransform(const vec &in, vec &out) const
- {
- vec p = vec(in).sub(vec(d));
- out.x = a.dot3(p);
- out.y = b.dot3(p);
- out.z = c.dot3(p);
- }
-
- void transposedtransformnormal(const vec &in, vec &out) const
- {
- out.x = a.dot3(in);
- out.y = b.dot3(in);
- out.z = c.dot3(in);
- }
-
- void transposedtransform(const plane &in, plane &out) const
- {
- out.x = in.dist(a);
- out.y = in.dist(b);
- out.z = in.dist(c);
- out.offset = in.dist(d);
- }
-
- float getscale() const
- {
- return sqrtf(a.x*a.y + b.x*b.x + c.x*c.x);
- }
-
- vec gettranslation() const
- {
- return vec(d);
- }
-
- vec4 rowx() const { return vec4(a.x, b.x, c.x, d.x); }
- vec4 rowy() const { return vec4(a.y, b.y, c.y, d.y); }
- vec4 rowz() const { return vec4(a.z, b.z, c.z, d.z); }
- vec4 roww() const { return vec4(a.w, b.w, c.w, d.w); }
-
- bool invert(const matrix4 &m, double mindet = 1.0e-12);
-
- vec2 lineardepthscale() const
- {
- return vec2(d.w, -d.z).div(c.z*d.w - d.z*c.w);
- }
+ vec4 a, b, c, d;
+
+ matrix4() {}
+ matrix4(const float *m) : a(m), b(m+4), c(m+8), d(m+12) {}
+ matrix4(const vec &a, const vec &b, const vec &c = vec(0, 0, 1))
+ : a(a.x, b.x, c.x, 0), b(a.y, b.y, c.y, 0), c(a.z, b.z, c.z, 0), d(0, 0, 0, 1)
+ {}
+ matrix4(const vec4 &a, const vec4 &b, const vec4 &c, const vec4 &d = vec4(0, 0, 0, 1))
+ : a(a), b(b), c(c), d(d)
+ {}
+ matrix4(const matrix4x3 &m)
+ : a(m.a, 0), b(m.b, 0), c(m.c, 0), d(m.d, 1)
+ {}
+ matrix4(const matrix3 &rot, const vec &trans)
+ : a(rot.a, 0), b(rot.b, 0), c(rot.c, 0), d(trans, 1)
+ {}
+
+ void mul(const matrix4 &x, const matrix3 &y)
+ {
+ a = vec4(x.a).mul(y.a.x).madd(x.b, y.a.y).madd(x.c, y.a.z);
+ b = vec4(x.a).mul(y.b.x).madd(x.b, y.b.y).madd(x.c, y.b.z);
+ c = vec4(x.a).mul(y.c.x).madd(x.b, y.c.y).madd(x.c, y.c.z);
+ d = x.d;
+ }
+ void mul(const matrix3 &y) { mul(matrix4(*this), y); }
+
+ template<class T> void mult(const matrix4 &x, const matrix4 &y)
+ {
+ a = T(x.a).mul(y.a.x).madd(x.b, y.a.y).madd(x.c, y.a.z).madd(x.d, y.a.w);
+ b = T(x.a).mul(y.b.x).madd(x.b, y.b.y).madd(x.c, y.b.z).madd(x.d, y.b.w);
+ c = T(x.a).mul(y.c.x).madd(x.b, y.c.y).madd(x.c, y.c.z).madd(x.d, y.c.w);
+ d = T(x.a).mul(y.d.x).madd(x.b, y.d.y).madd(x.c, y.d.z).madd(x.d, y.d.w);
+ }
+
+ void mul(const matrix4 &x, const matrix4 &y) { mult<vec4>(x, y); }
+ void mul(const matrix4 &y) { mult<vec4>(matrix4(*this), y); }
+
+ void muld(const matrix4 &x, const matrix4 &y) { mult<dvec4>(x, y); }
+ void muld(const matrix4 &y) { mult<dvec4>(matrix4(*this), y); }
+
+ void rotate_around_x(float ck, float sk)
+ {
+ vec4 rb = vec4(b).mul(ck).madd(c, sk),
+ rc = vec4(c).mul(ck).msub(b, sk);
+ b = rb;
+ c = rc;
+ }
+ void rotate_around_x(float angle) { rotate_around_x(cosf(angle), sinf(angle)); }
+ void rotate_around_x(const vec2 &sc) { rotate_around_x(sc.x, sc.y); }
+
+ void rotate_around_y(float ck, float sk)
+ {
+ vec4 rc = vec4(c).mul(ck).madd(a, sk),
+ ra = vec4(a).mul(ck).msub(c, sk);
+ c = rc;
+ a = ra;
+ }
+ void rotate_around_y(float angle) { rotate_around_y(cosf(angle), sinf(angle)); }
+ void rotate_around_y(const vec2 &sc) { rotate_around_y(sc.x, sc.y); }
+
+ void rotate_around_z(float ck, float sk)
+ {
+ vec4 ra = vec4(a).mul(ck).madd(b, sk),
+ rb = vec4(b).mul(ck).msub(a, sk);
+ a = ra;
+ b = rb;
+ }
+ void rotate_around_z(float angle) { rotate_around_z(cosf(angle), sinf(angle)); }
+ void rotate_around_z(const vec2 &sc) { rotate_around_z(sc.x, sc.y); }
+
+ void rotate(float ck, float sk, const vec &axis)
+ {
+ matrix3 m;
+ m.rotate(ck, sk, axis);
+ mul(m);
+ }
+ void rotate(float angle, const vec &dir) { rotate(cosf(angle), sinf(angle), dir); }
+ void rotate(const vec2 &sc, const vec &dir) { rotate(sc.x, sc.y, dir); }
+
+ void identity()
+ {
+ a = vec4(1, 0, 0, 0);
+ b = vec4(0, 1, 0, 0);
+ c = vec4(0, 0, 1, 0);
+ d = vec4(0, 0, 0, 1);
+ }
+
+ void settranslation(const vec &v) { d.setxyz(v); }
+ void settranslation(float x, float y, float z) { d.x = x; d.y = y; d.z = z; }
+
+ void translate(const vec &p) { d.madd(a, p.x).madd(b, p.y).madd(c, p.z); }
+ void translate(float x, float y, float z) { translate(vec(x, y, z)); }
+ void translate(const vec &p, float scale) { translate(vec(p).mul(scale)); }
+
+ void setscale(float x, float y, float z) { a.x = x; b.y = y; c.z = z; }
+ void setscale(const vec &v) { setscale(v.x, v.y, v.z); }
+ void setscale(float n) { setscale(n, n, n); }
+
+ void scale(float x, float y, float z)
+ {
+ a.mul(x);
+ b.mul(y);
+ c.mul(z);
+ }
+ void scale(const vec &v) { scale(v.x, v.y, v.z); }
+ void scale(float n) { scale(n, n, n); }
+
+ void scalexy(float x, float y)
+ {
+ a.x *= x; a.y *= y;
+ b.x *= x; b.y *= y;
+ c.x *= x; c.y *= y;
+ d.x *= x; d.y *= y;
+ }
+
+ void scalez(float k)
+ {
+ a.z *= k;
+ b.z *= k;
+ c.z *= k;
+ d.z *= k;
+ }
+
+ void reflectz(float z)
+ {
+ d.add(vec4(c).mul(2*z));
+ c.neg();
+ }
+
+ void projective(float zscale = 0.5f, float zoffset = 0.5f)
+ {
+ a.x = 0.5f*(a.x + a.w);
+ a.y = 0.5f*(a.y + a.w);
+ b.x = 0.5f*(b.x + b.w);
+ b.y = 0.5f*(b.y + b.w);
+ c.x = 0.5f*(c.x + c.w);
+ c.y = 0.5f*(c.y + c.w);
+ d.x = 0.5f*(d.x + d.w);
+ d.y = 0.5f*(d.y + d.w);
+ a.z = zscale*a.z + zoffset*a.w;
+ b.z = zscale*b.z + zoffset*b.w;
+ c.z = zscale*c.z + zoffset*c.w;
+ d.z = zscale*d.z + zoffset*d.w;
+ }
+
+ void jitter(float x, float y)
+ {
+ a.x += x * a.w;
+ a.y += y * a.w;
+ b.x += x * b.w;
+ b.y += y * b.w;
+ c.x += x * c.w;
+ c.y += y * c.w;
+ d.x += x * d.w;
+ d.y += y * d.w;
+ }
+
+ void transpose()
+ {
+ swap(a.y, b.x); swap(a.z, c.x); swap(a.w, d.x);
+ swap(b.z, c.y); swap(b.w, d.y);
+ swap(c.w, d.z);
+ }
+
+ void transpose(const matrix4 &m)
+ {
+ a = vec4(m.a.x, m.b.x, m.c.x, m.d.x);
+ b = vec4(m.a.y, m.b.y, m.c.y, m.d.y);
+ c = vec4(m.a.z, m.b.z, m.c.z, m.d.z);
+ d = vec4(m.a.w, m.b.w, m.c.w, m.d.w);
+ }
+
+ void frustum(float left, float right, float bottom, float top, float znear, float zfar)
+ {
+ float width = right - left, height = top - bottom, zrange = znear - zfar;
+ a = vec4(2*znear/width, 0, 0, 0);
+ b = vec4(0, 2*znear/height, 0, 0);
+ c = vec4((right + left)/width, (top + bottom)/height, (zfar + znear)/zrange, -1);
+ d = vec4(0, 0, 2*znear*zfar/zrange, 0);
+ }
+
+ void perspective(float fovy, float aspect, float znear, float zfar)
+ {
+ float ydist = znear * tan(fovy/2*RAD), xdist = ydist * aspect;
+ frustum(-xdist, xdist, -ydist, ydist, znear, zfar);
+ }
+
+ void ortho(float left, float right, float bottom, float top, float znear, float zfar)
+ {
+ float width = right - left, height = top - bottom, zrange = znear - zfar;
+ a = vec4(2/width, 0, 0, 0);
+ b = vec4(0, 2/height, 0, 0);
+ c = vec4(0, 0, 2/zrange, 0);
+ d = vec4(-(right+left)/width, -(top+bottom)/height, (zfar+znear)/zrange, 1);
+ }
+
+ void clip(const plane &p, const matrix4 &m)
+ {
+ float x = ((p.x<0 ? -1 : (p.x>0 ? 1 : 0)) + m.c.x) / m.a.x,
+ y = ((p.y<0 ? -1 : (p.y>0 ? 1 : 0)) + m.c.y) / m.b.y,
+ w = (1 + m.c.z) / m.d.z,
+ scale = 2 / (x*p.x + y*p.y - p.z + w*p.offset);
+ a = vec4(m.a.x, m.a.y, p.x*scale, m.a.w);
+ b = vec4(m.b.x, m.b.y, p.y*scale, m.b.w);
+ c = vec4(m.c.x, m.c.y, p.z*scale + 1.0f, m.c.w);
+ d = vec4(m.d.x, m.d.y, p.offset*scale, m.d.w);
+ }
+
+ void transform(const vec &in, vec &out) const
+ {
+ out = vec(a).mul(in.x).add(vec(b).mul(in.y)).add(vec(c).mul(in.z)).add(vec(d));
+ }
+
+ void transform(const vec4 &in, vec &out) const
+ {
+ out = vec(a).mul(in.x).add(vec(b).mul(in.y)).add(vec(c).mul(in.z)).add(vec(d).mul(in.w));
+ }
+
+ void transform(const vec &in, vec4 &out) const
+ {
+ out = vec4(a).mul(in.x).madd(b, in.y).madd(c, in.z).add(d);
+ }
+
+ void transform(const vec4 &in, vec4 &out) const
+ {
+ out = vec4(a).mul(in.x).madd(b, in.y).madd(c, in.z).madd(d, in.w);
+ }
+
+ template<class T, class U> T transform(const U &in) const
+ {
+ T v;
+ transform(in, v);
+ return v;
+ }
+
+ template<class T> vec perspectivetransform(const T &in) const
+ {
+ vec4 v;
+ transform(in, v);
+ return vec(v).div(v.w);
+ }
+
+ void transformnormal(const vec &in, vec &out) const
+ {
+ out = vec(a).mul(in.x).add(vec(b).mul(in.y)).add(vec(c).mul(in.z));
+ }
+
+ void transformnormal(const vec &in, vec4 &out) const
+ {
+ out = vec4(a).mul(in.x).madd(b, in.y).madd(c, in.z);
+ }
+
+ template<class T, class U> T transformnormal(const U &in) const
+ {
+ T v;
+ transformnormal(in, v);
+ return v;
+ }
+
+ void transposedtransform(const vec &in, vec &out) const
+ {
+ vec p = vec(in).sub(vec(d));
+ out.x = a.dot3(p);
+ out.y = b.dot3(p);
+ out.z = c.dot3(p);
+ }
+
+ void transposedtransformnormal(const vec &in, vec &out) const
+ {
+ out.x = a.dot3(in);
+ out.y = b.dot3(in);
+ out.z = c.dot3(in);
+ }
+
+ void transposedtransform(const plane &in, plane &out) const
+ {
+ out.x = in.dist(a);
+ out.y = in.dist(b);
+ out.z = in.dist(c);
+ out.offset = in.dist(d);
+ }
+
+ float getscale() const
+ {
+ return sqrtf(a.x*a.y + b.x*b.x + c.x*c.x);
+ }
+
+ vec gettranslation() const
+ {
+ return vec(d);
+ }
+
+ vec4 rowx() const { return vec4(a.x, b.x, c.x, d.x); }
+ vec4 rowy() const { return vec4(a.y, b.y, c.y, d.y); }
+ vec4 rowz() const { return vec4(a.z, b.z, c.z, d.z); }
+ vec4 roww() const { return vec4(a.w, b.w, c.w, d.w); }
+
+ bool invert(const matrix4 &m, double mindet = 1.0e-12);
+
+ vec2 lineardepthscale() const
+ {
+ return vec2(d.w, -d.z).div(c.z*d.w - d.z*c.w);
+ }
};
inline matrix3::matrix3(const matrix4 &m)
- : a(m.a), b(m.b), c(m.c)
+ : a(m.a), b(m.b), c(m.c)
{}
inline matrix4x3::matrix4x3(const matrix4 &m)
- : a(m.a), b(m.b), c(m.c), d(m.d)
+ : a(m.a), b(m.b), c(m.c), d(m.d)
{}
struct matrix2
{
- vec2 a, b;
+ vec2 a, b;
- matrix2() {}
- matrix2(const vec2 &a, const vec2 &b) : a(a), b(b) {}
- explicit matrix2(const matrix4 &m) : a(m.a), b(m.b) {}
- explicit matrix2(const matrix3 &m) : a(m.a), b(m.b) {}
+ matrix2() {}
+ matrix2(const vec2 &a, const vec2 &b) : a(a), b(b) {}
+ explicit matrix2(const matrix4 &m) : a(m.a), b(m.b) {}
+ explicit matrix2(const matrix3 &m) : a(m.a), b(m.b) {}
};
struct squat
{
- short x, y, z, w;
-
- squat() {}
- squat(const vec4 &q) { convert(q); }
-
- void convert(const vec4 &q)
- {
- x = short(q.x*32767.5f-0.5f);
- y = short(q.y*32767.5f-0.5f);
- z = short(q.z*32767.5f-0.5f);
- w = short(q.w*32767.5f-0.5f);
- }
-
- void lerp(const vec4 &a, const vec4 &b, float t)
- {
- vec4 q;
- q.lerp(a, b, t);
- convert(q);
- }
+ short x, y, z, w;
+
+ squat() {}
+ squat(const vec4 &q) { convert(q); }
+
+ void convert(const vec4 &q)
+ {
+ x = short(q.x*32767.5f-0.5f);
+ y = short(q.y*32767.5f-0.5f);
+ z = short(q.z*32767.5f-0.5f);
+ w = short(q.w*32767.5f-0.5f);
+ }
+
+ void lerp(const vec4 &a, const vec4 &b, float t)
+ {
+ vec4 q;
+ q.lerp(a, b, t);
+ convert(q);
+ }
};
extern bool raysphereintersect(const vec &center, float radius, const vec &o, const vec &ray, float &dist);
@@ -1816,9 +1816,9 @@ extern bool linecylinderintersect(const vec &from, const vec &to, const vec &sta
extern const vec2 sincos360[];
static inline int mod360(int angle)
{
- if(angle < 0) angle = 360 + (angle <= -360 ? angle%360 : angle);
- else if(angle >= 360) angle %= 360;
- return angle;
+ if(angle < 0) angle = 360 + (angle <= -360 ? angle%360 : angle);
+ else if(angle >= 360) angle %= 360;
+ return angle;
}
static inline const vec2 &sincosmod360(int angle) { return sincos360[mod360(angle)]; }
static inline float cos360(int angle) { return sincos360[angle].x; }
diff --git a/src/shared/glemu.cpp b/src/shared/glemu.cpp
index 5658eb8..58e071d 100644
--- a/src/shared/glemu.cpp
+++ b/src/shared/glemu.cpp
@@ -5,351 +5,351 @@ extern int intel_mapbufferrange_bug;
namespace gle
{
- struct attribinfo
- {
- int type, size, formatsize, offset;
- GLenum format;
-
- attribinfo() : type(0), size(0), formatsize(0), offset(0), format(GL_FALSE) {}
-
- bool operator==(const attribinfo &a) const
- {
- return type == a.type && size == a.size && format == a.format && offset == a.offset;
- }
- bool operator!=(const attribinfo &a) const
- {
- return type != a.type || size != a.size || format != a.format || offset != a.offset;
- }
- };
-
- extern const char * const attribnames[MAXATTRIBS] = { "vvertex", "vcolor", "vtexcoord0", "vtexcoord1", "vnormal", "vtangent", "vboneweight", "vboneindex" };
- ucharbuf attribbuf;
- static uchar *attribdata;
- static attribinfo attribdefs[MAXATTRIBS], lastattribs[MAXATTRIBS];
- int enabled = 0;
- static int numattribs = 0, attribmask = 0, numlastattribs = 0, lastattribmask = 0, vertexsize = 0, lastvertexsize = 0;
- static GLenum primtype = GL_TRIANGLES;
- static uchar *lastbuf = NULL;
- static bool changedattribs = false;
- static vector<GLint> multidrawstart;
- static vector<GLsizei> multidrawcount;
-
- #define MAXQUADS (0x10000/4)
- static GLuint quadindexes = 0;
- static bool quadsenabled = false;
-
- #define MAXVBOSIZE (4*1024*1024)
- static GLuint vbo = 0;
- static int vbooffset = MAXVBOSIZE;
-
- static GLuint defaultvao = 0;
-
- void enablequads()
- {
- quadsenabled = true;
-
- if(glversion < 300) return;
-
- if(quadindexes)
- {
- glBindBuffer_(GL_ELEMENT_ARRAY_BUFFER, quadindexes);
- return;
- }
-
- glGenBuffers_(1, &quadindexes);
- ushort *data = new ushort[MAXQUADS*6], *dst = data;
- for(int idx = 0; idx < MAXQUADS*4; idx += 4, dst += 6)
- {
- dst[0] = idx;
- dst[1] = idx + 1;
- dst[2] = idx + 2;
- dst[3] = idx + 0;
- dst[4] = idx + 2;
- dst[5] = idx + 3;
- }
- glBindBuffer_(GL_ELEMENT_ARRAY_BUFFER, quadindexes);
- glBufferData_(GL_ELEMENT_ARRAY_BUFFER, MAXQUADS*6*sizeof(ushort), data, GL_STATIC_DRAW);
- delete[] data;
- }
-
- void disablequads()
- {
- quadsenabled = false;
-
- if(glversion < 300) return;
-
- glBindBuffer_(GL_ELEMENT_ARRAY_BUFFER, 0);
- }
-
- void drawquads(int offset, int count)
- {
- if(count <= 0) return;
- if(glversion < 300)
- {
- glDrawArrays(GL_QUADS, offset*4, count*4);
- return;
- }
- if(offset + count > MAXQUADS)
- {
- if(offset >= MAXQUADS) return;
- count = MAXQUADS - offset;
- }
- glDrawRangeElements_(GL_TRIANGLES, offset*4, (offset + count)*4-1, count*6, GL_UNSIGNED_SHORT, (ushort *)0 + offset*6);
- }
-
- void defattrib(int type, int size, int format)
- {
- if(type == ATTRIB_VERTEX)
- {
- numattribs = attribmask = 0;
- vertexsize = 0;
- }
- changedattribs = true;
- attribmask |= 1<<type;
- attribinfo &a = attribdefs[numattribs++];
- a.type = type;
- a.size = size;
- a.format = format;
- switch(format)
- {
- case 'B': case GL_UNSIGNED_BYTE: a.formatsize = 1; a.format = GL_UNSIGNED_BYTE; break;
- case 'b': case GL_BYTE: a.formatsize = 1; a.format = GL_BYTE; break;
- case 'S': case GL_UNSIGNED_SHORT: a.formatsize = 2; a.format = GL_UNSIGNED_SHORT; break;
- case 's': case GL_SHORT: a.formatsize = 2; a.format = GL_SHORT; break;
- case 'I': case GL_UNSIGNED_INT: a.formatsize = 4; a.format = GL_UNSIGNED_INT; break;
- case 'i': case GL_INT: a.formatsize = 4; a.format = GL_INT; break;
- case 'f': case GL_FLOAT: a.formatsize = 4; a.format = GL_FLOAT; break;
- case 'd': case GL_DOUBLE: a.formatsize = 8; a.format = GL_DOUBLE; break;
- default: a.formatsize = 0; a.format = GL_FALSE; break;
- }
- a.formatsize *= size;
- a.offset = vertexsize;
- vertexsize += a.formatsize;
- }
-
- void defattribs(const char *fmt)
- {
- for(;; fmt += 3)
- {
- GLenum format;
- switch(fmt[0])
- {
- case 'v': format = ATTRIB_VERTEX; break;
- case 'c': format = ATTRIB_COLOR; break;
- case 't': format = ATTRIB_TEXCOORD0; break;
- case 'T': format = ATTRIB_TEXCOORD1; break;
- case 'n': format = ATTRIB_NORMAL; break;
- case 'x': format = ATTRIB_TANGENT; break;
- case 'w': format = ATTRIB_BONEWEIGHT; break;
- case 'i': format = ATTRIB_BONEINDEX; break;
- default: return;
- }
- defattrib(format, fmt[1]-'0', fmt[2]);
- }
- }
-
- static inline void setattrib(const attribinfo &a, uchar *buf)
- {
- switch(a.type)
- {
- case ATTRIB_VERTEX:
- case ATTRIB_TEXCOORD0:
- case ATTRIB_TEXCOORD1:
- case ATTRIB_BONEINDEX:
- glVertexAttribPointer_(a.type, a.size, a.format, GL_FALSE, vertexsize, buf);
- break;
- case ATTRIB_COLOR:
- case ATTRIB_NORMAL:
- case ATTRIB_TANGENT:
- case ATTRIB_BONEWEIGHT:
- glVertexAttribPointer_(a.type, a.size, a.format, GL_TRUE, vertexsize, buf);
- break;
- }
- if(!(enabled&(1<<a.type)))
- {
- glEnableVertexAttribArray_(a.type);
- enabled |= 1<<a.type;
- }
- }
-
- static inline void unsetattrib(const attribinfo &a)
- {
- glDisableVertexAttribArray_(a.type);
- enabled &= ~(1<<a.type);
- }
-
- static inline void setattribs(uchar *buf)
- {
- bool forceattribs = numattribs != numlastattribs || vertexsize != lastvertexsize || buf != lastbuf;
- if(forceattribs || changedattribs)
- {
- int diffmask = enabled & lastattribmask & ~attribmask;
- if(diffmask) loopi(numlastattribs)
- {
- const attribinfo &a = lastattribs[i];
- if(diffmask & (1<<a.type)) unsetattrib(a);
- }
- uchar *src = buf;
- loopi(numattribs)
- {
- const attribinfo &a = attribdefs[i];
- if(forceattribs || a != lastattribs[i])
- {
- setattrib(a, src);
- lastattribs[i] = a;
- }
- src += a.formatsize;
- }
- lastbuf = buf;
- numlastattribs = numattribs;
- lastattribmask = attribmask;
- lastvertexsize = vertexsize;
- changedattribs = false;
- }
- }
-
- void begin(GLenum mode)
- {
- primtype = mode;
- }
-
- void begin(GLenum mode, int numverts)
- {
- primtype = mode;
- if(glversion >= 300 && !intel_mapbufferrange_bug)
- {
- int len = numverts * vertexsize;
- if(vbooffset + len >= MAXVBOSIZE)
- {
- len = min(len, MAXVBOSIZE);
- if(!vbo) glGenBuffers_(1, &vbo);
- glBindBuffer_(GL_ARRAY_BUFFER, vbo);
- glBufferData_(GL_ARRAY_BUFFER, MAXVBOSIZE, NULL, GL_STREAM_DRAW);
- vbooffset = 0;
- }
- else if(!lastvertexsize) glBindBuffer_(GL_ARRAY_BUFFER, vbo);
- void *buf = glMapBufferRange_(GL_ARRAY_BUFFER, vbooffset, len, GL_MAP_WRITE_BIT|GL_MAP_INVALIDATE_RANGE_BIT|GL_MAP_UNSYNCHRONIZED_BIT);
- if(buf) attribbuf.reset((uchar *)buf, len);
- }
- }
-
- void multidraw()
- {
- int start = multidrawstart.length() ? multidrawstart.last() + multidrawcount.last() : 0,
- count = attribbuf.length()/vertexsize - start;
- if(count > 0)
- {
- multidrawstart.add(start);
- multidrawcount.add(count);
- }
- }
-
- int end()
- {
- uchar *buf = attribbuf.getbuf();
- if(attribbuf.empty())
- {
- if(buf != attribdata)
- {
- glUnmapBuffer_(GL_ARRAY_BUFFER);
- attribbuf.reset(attribdata, MAXVBOSIZE);
- }
- return 0;
- }
- int start = 0;
- if(glversion >= 300)
- {
- if(buf == attribdata)
- {
- if(vbooffset + attribbuf.length() >= MAXVBOSIZE)
- {
- if(!vbo) glGenBuffers_(1, &vbo);
- glBindBuffer_(GL_ARRAY_BUFFER, vbo);
- glBufferData_(GL_ARRAY_BUFFER, MAXVBOSIZE, NULL, GL_STREAM_DRAW);
- vbooffset = 0;
- }
- else if(!lastvertexsize) glBindBuffer_(GL_ARRAY_BUFFER, vbo);
- void *dst = intel_mapbufferrange_bug ? NULL :
- glMapBufferRange_(GL_ARRAY_BUFFER, vbooffset, attribbuf.length(), GL_MAP_WRITE_BIT|GL_MAP_INVALIDATE_RANGE_BIT|GL_MAP_UNSYNCHRONIZED_BIT);
- if(dst)
- {
- memcpy(dst, attribbuf.getbuf(), attribbuf.length());
- glUnmapBuffer_(GL_ARRAY_BUFFER);
- }
- else glBufferSubData_(GL_ARRAY_BUFFER, vbooffset, attribbuf.length(), attribbuf.getbuf());
- }
- else glUnmapBuffer_(GL_ARRAY_BUFFER);
- buf = (uchar *)0 + vbooffset;
- if(vertexsize == lastvertexsize && buf >= lastbuf)
- {
- start = int(buf - lastbuf)/vertexsize;
- if(primtype == GL_QUADS && (start%4 || start + attribbuf.length()/vertexsize >= 4*MAXQUADS))
- start = 0;
- else buf = lastbuf;
- }
- vbooffset += attribbuf.length();
- }
- setattribs(buf);
- int numvertexes = attribbuf.length()/vertexsize;
- if(primtype == GL_QUADS)
- {
- if(!quadsenabled) enablequads();
- for(int quads = numvertexes/4;;)
- {
- int count = min(quads, MAXQUADS);
- drawquads(start/4, count);
- quads -= count;
- if(quads <= 0) break;
- setattribs(buf + 4*count*vertexsize);
- start = 0;
- }
- }
- else
- {
- if(multidrawstart.length())
- {
- multidraw();
- if(start) loopv(multidrawstart) multidrawstart[i] += start;
- glMultiDrawArrays_(primtype, multidrawstart.getbuf(), multidrawcount.getbuf(), multidrawstart.length());
- multidrawstart.setsize(0);
- multidrawcount.setsize(0);
- }
- else glDrawArrays(primtype, start, numvertexes);
- }
- attribbuf.reset(attribdata, MAXVBOSIZE);
- return numvertexes;
- }
-
- void forcedisable()
- {
- for(int i = 0; enabled; i++) if(enabled&(1<<i)) { glDisableVertexAttribArray_(i); enabled &= ~(1<<i); }
- numlastattribs = lastattribmask = lastvertexsize = 0;
- lastbuf = NULL;
- if(quadsenabled) disablequads();
- if(glversion >= 300) glBindBuffer_(GL_ARRAY_BUFFER, 0);
- }
-
- void setup()
- {
- if(glversion >= 300)
- {
- if(!defaultvao) glGenVertexArrays_(1, &defaultvao);
- glBindVertexArray_(defaultvao);
- }
- attribdata = new uchar[MAXVBOSIZE];
- attribbuf.reset(attribdata, MAXVBOSIZE);
- }
-
- void cleanup()
- {
- disable();
-
- if(quadindexes) { glDeleteBuffers_(1, &quadindexes); quadindexes = 0; }
-
- if(vbo) { glDeleteBuffers_(1, &vbo); vbo = 0; }
- vbooffset = MAXVBOSIZE;
-
- if(defaultvao) { glDeleteVertexArrays_(1, &defaultvao); defaultvao = 0; }
- }
+ struct attribinfo
+ {
+ int type, size, formatsize, offset;
+ GLenum format;
+
+ attribinfo() : type(0), size(0), formatsize(0), offset(0), format(GL_FALSE) {}
+
+ bool operator==(const attribinfo &a) const
+ {
+ return type == a.type && size == a.size && format == a.format && offset == a.offset;
+ }
+ bool operator!=(const attribinfo &a) const
+ {
+ return type != a.type || size != a.size || format != a.format || offset != a.offset;
+ }
+ };
+
+ extern const char * const attribnames[MAXATTRIBS] = { "vvertex", "vcolor", "vtexcoord0", "vtexcoord1", "vnormal", "vtangent", "vboneweight", "vboneindex" };
+ ucharbuf attribbuf;
+ static uchar *attribdata;
+ static attribinfo attribdefs[MAXATTRIBS], lastattribs[MAXATTRIBS];
+ int enabled = 0;
+ static int numattribs = 0, attribmask = 0, numlastattribs = 0, lastattribmask = 0, vertexsize = 0, lastvertexsize = 0;
+ static GLenum primtype = GL_TRIANGLES;
+ static uchar *lastbuf = NULL;
+ static bool changedattribs = false;
+ static vector<GLint> multidrawstart;
+ static vector<GLsizei> multidrawcount;
+
+ #define MAXQUADS (0x10000/4)
+ static GLuint quadindexes = 0;
+ static bool quadsenabled = false;
+
+ #define MAXVBOSIZE (4*1024*1024)
+ static GLuint vbo = 0;
+ static int vbooffset = MAXVBOSIZE;
+
+ static GLuint defaultvao = 0;
+
+ void enablequads()
+ {
+ quadsenabled = true;
+
+ if(glversion < 300) return;
+
+ if(quadindexes)
+ {
+ glBindBuffer_(GL_ELEMENT_ARRAY_BUFFER, quadindexes);
+ return;
+ }
+
+ glGenBuffers_(1, &quadindexes);
+ ushort *data = new ushort[MAXQUADS*6], *dst = data;
+ for(int idx = 0; idx < MAXQUADS*4; idx += 4, dst += 6)
+ {
+ dst[0] = idx;
+ dst[1] = idx + 1;
+ dst[2] = idx + 2;
+ dst[3] = idx + 0;
+ dst[4] = idx + 2;
+ dst[5] = idx + 3;
+ }
+ glBindBuffer_(GL_ELEMENT_ARRAY_BUFFER, quadindexes);
+ glBufferData_(GL_ELEMENT_ARRAY_BUFFER, MAXQUADS*6*sizeof(ushort), data, GL_STATIC_DRAW);
+ delete[] data;
+ }
+
+ void disablequads()
+ {
+ quadsenabled = false;
+
+ if(glversion < 300) return;
+
+ glBindBuffer_(GL_ELEMENT_ARRAY_BUFFER, 0);
+ }
+
+ void drawquads(int offset, int count)
+ {
+ if(count <= 0) return;
+ if(glversion < 300)
+ {
+ glDrawArrays(GL_QUADS, offset*4, count*4);
+ return;
+ }
+ if(offset + count > MAXQUADS)
+ {
+ if(offset >= MAXQUADS) return;
+ count = MAXQUADS - offset;
+ }
+ glDrawRangeElements_(GL_TRIANGLES, offset*4, (offset + count)*4-1, count*6, GL_UNSIGNED_SHORT, (ushort *)0 + offset*6);
+ }
+
+ void defattrib(int type, int size, int format)
+ {
+ if(type == ATTRIB_VERTEX)
+ {
+ numattribs = attribmask = 0;
+ vertexsize = 0;
+ }
+ changedattribs = true;
+ attribmask |= 1<<type;
+ attribinfo &a = attribdefs[numattribs++];
+ a.type = type;
+ a.size = size;
+ a.format = format;
+ switch(format)
+ {
+ case 'B': case GL_UNSIGNED_BYTE: a.formatsize = 1; a.format = GL_UNSIGNED_BYTE; break;
+ case 'b': case GL_BYTE: a.formatsize = 1; a.format = GL_BYTE; break;
+ case 'S': case GL_UNSIGNED_SHORT: a.formatsize = 2; a.format = GL_UNSIGNED_SHORT; break;
+ case 's': case GL_SHORT: a.formatsize = 2; a.format = GL_SHORT; break;
+ case 'I': case GL_UNSIGNED_INT: a.formatsize = 4; a.format = GL_UNSIGNED_INT; break;
+ case 'i': case GL_INT: a.formatsize = 4; a.format = GL_INT; break;
+ case 'f': case GL_FLOAT: a.formatsize = 4; a.format = GL_FLOAT; break;
+ case 'd': case GL_DOUBLE: a.formatsize = 8; a.format = GL_DOUBLE; break;
+ default: a.formatsize = 0; a.format = GL_FALSE; break;
+ }
+ a.formatsize *= size;
+ a.offset = vertexsize;
+ vertexsize += a.formatsize;
+ }
+
+ void defattribs(const char *fmt)
+ {
+ for(;; fmt += 3)
+ {
+ GLenum format;
+ switch(fmt[0])
+ {
+ case 'v': format = ATTRIB_VERTEX; break;
+ case 'c': format = ATTRIB_COLOR; break;
+ case 't': format = ATTRIB_TEXCOORD0; break;
+ case 'T': format = ATTRIB_TEXCOORD1; break;
+ case 'n': format = ATTRIB_NORMAL; break;
+ case 'x': format = ATTRIB_TANGENT; break;
+ case 'w': format = ATTRIB_BONEWEIGHT; break;
+ case 'i': format = ATTRIB_BONEINDEX; break;
+ default: return;
+ }
+ defattrib(format, fmt[1]-'0', fmt[2]);
+ }
+ }
+
+ static inline void setattrib(const attribinfo &a, uchar *buf)
+ {
+ switch(a.type)
+ {
+ case ATTRIB_VERTEX:
+ case ATTRIB_TEXCOORD0:
+ case ATTRIB_TEXCOORD1:
+ case ATTRIB_BONEINDEX:
+ glVertexAttribPointer_(a.type, a.size, a.format, GL_FALSE, vertexsize, buf);
+ break;
+ case ATTRIB_COLOR:
+ case ATTRIB_NORMAL:
+ case ATTRIB_TANGENT:
+ case ATTRIB_BONEWEIGHT:
+ glVertexAttribPointer_(a.type, a.size, a.format, GL_TRUE, vertexsize, buf);
+ break;
+ }
+ if(!(enabled&(1<<a.type)))
+ {
+ glEnableVertexAttribArray_(a.type);
+ enabled |= 1<<a.type;
+ }
+ }
+
+ static inline void unsetattrib(const attribinfo &a)
+ {
+ glDisableVertexAttribArray_(a.type);
+ enabled &= ~(1<<a.type);
+ }
+
+ static inline void setattribs(uchar *buf)
+ {
+ bool forceattribs = numattribs != numlastattribs || vertexsize != lastvertexsize || buf != lastbuf;
+ if(forceattribs || changedattribs)
+ {
+ int diffmask = enabled & lastattribmask & ~attribmask;
+ if(diffmask) loopi(numlastattribs)
+ {
+ const attribinfo &a = lastattribs[i];
+ if(diffmask & (1<<a.type)) unsetattrib(a);
+ }
+ uchar *src = buf;
+ loopi(numattribs)
+ {
+ const attribinfo &a = attribdefs[i];
+ if(forceattribs || a != lastattribs[i])
+ {
+ setattrib(a, src);
+ lastattribs[i] = a;
+ }
+ src += a.formatsize;
+ }
+ lastbuf = buf;
+ numlastattribs = numattribs;
+ lastattribmask = attribmask;
+ lastvertexsize = vertexsize;
+ changedattribs = false;
+ }
+ }
+
+ void begin(GLenum mode)
+ {
+ primtype = mode;
+ }
+
+ void begin(GLenum mode, int numverts)
+ {
+ primtype = mode;
+ if(glversion >= 300 && !intel_mapbufferrange_bug)
+ {
+ int len = numverts * vertexsize;
+ if(vbooffset + len >= MAXVBOSIZE)
+ {
+ len = min(len, MAXVBOSIZE);
+ if(!vbo) glGenBuffers_(1, &vbo);
+ glBindBuffer_(GL_ARRAY_BUFFER, vbo);
+ glBufferData_(GL_ARRAY_BUFFER, MAXVBOSIZE, NULL, GL_STREAM_DRAW);
+ vbooffset = 0;
+ }
+ else if(!lastvertexsize) glBindBuffer_(GL_ARRAY_BUFFER, vbo);
+ void *buf = glMapBufferRange_(GL_ARRAY_BUFFER, vbooffset, len, GL_MAP_WRITE_BIT|GL_MAP_INVALIDATE_RANGE_BIT|GL_MAP_UNSYNCHRONIZED_BIT);
+ if(buf) attribbuf.reset((uchar *)buf, len);
+ }
+ }
+
+ void multidraw()
+ {
+ int start = multidrawstart.length() ? multidrawstart.last() + multidrawcount.last() : 0,
+ count = attribbuf.length()/vertexsize - start;
+ if(count > 0)
+ {
+ multidrawstart.add(start);
+ multidrawcount.add(count);
+ }
+ }
+
+ int end()
+ {
+ uchar *buf = attribbuf.getbuf();
+ if(attribbuf.empty())
+ {
+ if(buf != attribdata)
+ {
+ glUnmapBuffer_(GL_ARRAY_BUFFER);
+ attribbuf.reset(attribdata, MAXVBOSIZE);
+ }
+ return 0;
+ }
+ int start = 0;
+ if(glversion >= 300)
+ {
+ if(buf == attribdata)
+ {
+ if(vbooffset + attribbuf.length() >= MAXVBOSIZE)
+ {
+ if(!vbo) glGenBuffers_(1, &vbo);
+ glBindBuffer_(GL_ARRAY_BUFFER, vbo);
+ glBufferData_(GL_ARRAY_BUFFER, MAXVBOSIZE, NULL, GL_STREAM_DRAW);
+ vbooffset = 0;
+ }
+ else if(!lastvertexsize) glBindBuffer_(GL_ARRAY_BUFFER, vbo);
+ void *dst = intel_mapbufferrange_bug ? NULL :
+ glMapBufferRange_(GL_ARRAY_BUFFER, vbooffset, attribbuf.length(), GL_MAP_WRITE_BIT|GL_MAP_INVALIDATE_RANGE_BIT|GL_MAP_UNSYNCHRONIZED_BIT);
+ if(dst)
+ {
+ memcpy(dst, attribbuf.getbuf(), attribbuf.length());
+ glUnmapBuffer_(GL_ARRAY_BUFFER);
+ }
+ else glBufferSubData_(GL_ARRAY_BUFFER, vbooffset, attribbuf.length(), attribbuf.getbuf());
+ }
+ else glUnmapBuffer_(GL_ARRAY_BUFFER);
+ buf = (uchar *)0 + vbooffset;
+ if(vertexsize == lastvertexsize && buf >= lastbuf)
+ {
+ start = int(buf - lastbuf)/vertexsize;
+ if(primtype == GL_QUADS && (start%4 || start + attribbuf.length()/vertexsize >= 4*MAXQUADS))
+ start = 0;
+ else buf = lastbuf;
+ }
+ vbooffset += attribbuf.length();
+ }
+ setattribs(buf);
+ int numvertexes = attribbuf.length()/vertexsize;
+ if(primtype == GL_QUADS)
+ {
+ if(!quadsenabled) enablequads();
+ for(int quads = numvertexes/4;;)
+ {
+ int count = min(quads, MAXQUADS);
+ drawquads(start/4, count);
+ quads -= count;
+ if(quads <= 0) break;
+ setattribs(buf + 4*count*vertexsize);
+ start = 0;
+ }
+ }
+ else
+ {
+ if(multidrawstart.length())
+ {
+ multidraw();
+ if(start) loopv(multidrawstart) multidrawstart[i] += start;
+ glMultiDrawArrays_(primtype, multidrawstart.getbuf(), multidrawcount.getbuf(), multidrawstart.length());
+ multidrawstart.setsize(0);
+ multidrawcount.setsize(0);
+ }
+ else glDrawArrays(primtype, start, numvertexes);
+ }
+ attribbuf.reset(attribdata, MAXVBOSIZE);
+ return numvertexes;
+ }
+
+ void forcedisable()
+ {
+ for(int i = 0; enabled; i++) if(enabled&(1<<i)) { glDisableVertexAttribArray_(i); enabled &= ~(1<<i); }
+ numlastattribs = lastattribmask = lastvertexsize = 0;
+ lastbuf = NULL;
+ if(quadsenabled) disablequads();
+ if(glversion >= 300) glBindBuffer_(GL_ARRAY_BUFFER, 0);
+ }
+
+ void setup()
+ {
+ if(glversion >= 300)
+ {
+ if(!defaultvao) glGenVertexArrays_(1, &defaultvao);
+ glBindVertexArray_(defaultvao);
+ }
+ attribdata = new uchar[MAXVBOSIZE];
+ attribbuf.reset(attribdata, MAXVBOSIZE);
+ }
+
+ void cleanup()
+ {
+ disable();
+
+ if(quadindexes) { glDeleteBuffers_(1, &quadindexes); quadindexes = 0; }
+
+ if(vbo) { glDeleteBuffers_(1, &vbo); vbo = 0; }
+ vbooffset = MAXVBOSIZE;
+
+ if(defaultvao) { glDeleteVertexArrays_(1, &defaultvao); defaultvao = 0; }
+ }
}
diff --git a/src/shared/glemu.h b/src/shared/glemu.h
index 94af8f9..e4f4d26 100644
--- a/src/shared/glemu.h
+++ b/src/shared/glemu.h
@@ -1,180 +1,180 @@
namespace gle
{
- enum
- {
- ATTRIB_VERTEX = 0,
- ATTRIB_COLOR = 1,
- ATTRIB_TEXCOORD0 = 2,
- ATTRIB_TEXCOORD1 = 3,
- ATTRIB_NORMAL = 4,
- ATTRIB_TANGENT = 5,
- ATTRIB_BONEWEIGHT = 6,
- ATTRIB_BONEINDEX = 7,
- MAXATTRIBS = 8
- };
-
- extern const char * const attribnames[MAXATTRIBS];
- extern ucharbuf attribbuf;
-
- extern int enabled;
- extern void forcedisable();
- static inline void disable() { if(enabled) forcedisable(); }
-
- extern void begin(GLenum mode);
- extern void begin(GLenum mode, int numverts);
- extern void defattribs(const char *fmt);
- extern void defattrib(int type, int size, int format);
-
- #define GLE_DEFATTRIB(name, type, defaultsize, defaultformat) \
- static inline void def##name(int size = defaultsize, int format = defaultformat) { defattrib(type, size, format); }
-
- GLE_DEFATTRIB(vertex, ATTRIB_VERTEX, 3, GL_FLOAT)
- GLE_DEFATTRIB(color, ATTRIB_COLOR, 3, GL_FLOAT)
- GLE_DEFATTRIB(texcoord0, ATTRIB_TEXCOORD0, 2, GL_FLOAT)
- GLE_DEFATTRIB(texcoord1, ATTRIB_TEXCOORD1, 2, GL_FLOAT)
- GLE_DEFATTRIB(normal, ATTRIB_NORMAL, 3, GL_FLOAT)
- GLE_DEFATTRIB(tangent, ATTRIB_TANGENT, 4, GL_FLOAT)
- GLE_DEFATTRIB(boneweight, ATTRIB_BONEWEIGHT, 4, GL_UNSIGNED_BYTE)
- GLE_DEFATTRIB(boneindex, ATTRIB_BONEINDEX, 4, GL_UNSIGNED_BYTE)
-
- #define GLE_INITATTRIB(name, index, suffix, type) \
- static inline void name##suffix(type x) { glVertexAttrib1##suffix##_(index, x); } \
- static inline void name##suffix(type x, type y) { glVertexAttrib2##suffix##_(index, x, y); } \
- static inline void name##suffix(type x, type y, type z) { glVertexAttrib3##suffix##_(index, x, y, z); } \
- static inline void name##suffix(type x, type y, type z, type w) { glVertexAttrib4##suffix##_(index, x, y, z, w); }
- #define GLE_INITATTRIBF(name, index) \
- GLE_INITATTRIB(name, index, f, float) \
- static inline void name(const vec &v) { glVertexAttrib3fv_(index, v.v); } \
- static inline void name(const vec &v, float w) { glVertexAttrib4f_(index, v.x, v.y, v.z, w); } \
- static inline void name(const vec2 &v) { glVertexAttrib2fv_(index, v.v); } \
- static inline void name(const vec4 &v) { glVertexAttrib4fv_(index, v.v); }
- #define GLE_INITATTRIBN(name, index, suffix, type, defaultw) \
- static inline void name##suffix(type x, type y, type z, type w = defaultw) { glVertexAttrib4N##suffix##_(index, x, y, z, w); }
-
- GLE_INITATTRIBF(vertex, ATTRIB_VERTEX)
- GLE_INITATTRIBF(color, ATTRIB_COLOR)
- static inline void color(const bvec4 &v) { glVertexAttrib4Nubv_(ATTRIB_COLOR, v.v); }
- static inline void color(const bvec &v, uchar alpha = 255) { color(bvec4(v, alpha)); }
- static inline void colorub(uchar x, uchar y, uchar z, uchar w = 255) { color(bvec4(x, y, z, w)); }
- GLE_INITATTRIBF(texcoord0, ATTRIB_TEXCOORD0)
- GLE_INITATTRIBF(texcoord1, ATTRIB_TEXCOORD1)
- static inline void normal(float x, float y, float z) { glVertexAttrib4f_(ATTRIB_NORMAL, x, y, z, 0.0f); }
- static inline void normal(const vec &v) { glVertexAttrib4f_(ATTRIB_NORMAL, v.x, v.y, v.z, 0.0f); }
- static inline void tangent(float x, float y, float z, float w = 1.0f) { glVertexAttrib4f_(ATTRIB_TANGENT, x, y, z, w); }
- static inline void tangent(const vec &v, float w = 1.0f) { glVertexAttrib4f_(ATTRIB_TANGENT, v.x, v.y, v.z, w); }
- static inline void tangent(const vec4 &v) { glVertexAttrib4fv_(ATTRIB_TANGENT, v.v); }
-
- #define GLE_ATTRIBPOINTER(name, index, defaultnormalized, defaultsize, defaulttype, prepare) \
- static inline void enable##name() { prepare; glEnableVertexAttribArray_(index); } \
- static inline void disable##name() { glDisableVertexAttribArray_(index); } \
- static inline void name##pointer(int stride, const void *data, GLenum type = defaulttype, int size = defaultsize, GLenum normalized = defaultnormalized) { \
- prepare; \
- glVertexAttribPointer_(index, size, type, normalized, stride, data); \
- }
-
- static inline void enableattrib(int index) { disable(); glEnableVertexAttribArray_(index); }
- static inline void disableattrib(int index) { glDisableVertexAttribArray_(index); }
- GLE_ATTRIBPOINTER(vertex, ATTRIB_VERTEX, GL_FALSE, 3, GL_FLOAT, disable())
- GLE_ATTRIBPOINTER(color, ATTRIB_COLOR, GL_TRUE, 4, GL_UNSIGNED_BYTE, )
- GLE_ATTRIBPOINTER(texcoord0, ATTRIB_TEXCOORD0, GL_FALSE, 2, GL_FLOAT, )
- GLE_ATTRIBPOINTER(texcoord1, ATTRIB_TEXCOORD1, GL_FALSE, 2, GL_FLOAT, )
- GLE_ATTRIBPOINTER(normal, ATTRIB_NORMAL, GL_TRUE, 3, GL_FLOAT, )
- GLE_ATTRIBPOINTER(tangent, ATTRIB_TANGENT, GL_TRUE, 4, GL_FLOAT, )
- GLE_ATTRIBPOINTER(boneweight, ATTRIB_BONEWEIGHT, GL_TRUE, 4, GL_UNSIGNED_BYTE, )
- GLE_ATTRIBPOINTER(boneindex, ATTRIB_BONEINDEX, GL_FALSE, 4, GL_UNSIGNED_BYTE, )
-
- static inline void bindebo(GLuint ebo) { disable(); glBindBuffer_(GL_ELEMENT_ARRAY_BUFFER, ebo); }
- static inline void clearebo() { glBindBuffer_(GL_ELEMENT_ARRAY_BUFFER, 0); }
- static inline void bindvbo(GLuint vbo) { disable(); glBindBuffer_(GL_ARRAY_BUFFER, vbo); }
- static inline void clearvbo() { glBindBuffer_(GL_ARRAY_BUFFER, 0); }
-
- template<class T>
- static inline void attrib(T x)
- {
- if(attribbuf.check(sizeof(T)))
- {
- T *buf = (T *)attribbuf.pad(sizeof(T));
- buf[0] = x;
- }
- }
-
- template<class T>
- static inline void attrib(T x, T y)
- {
- if(attribbuf.check(2*sizeof(T)))
- {
- T *buf = (T *)attribbuf.pad(2*sizeof(T));
- buf[0] = x;
- buf[1] = y;
- }
- }
-
- template<class T>
- static inline void attrib(T x, T y, T z)
- {
- if(attribbuf.check(3*sizeof(T)))
- {
- T *buf = (T *)attribbuf.pad(3*sizeof(T));
- buf[0] = x;
- buf[1] = y;
- buf[2] = z;
- }
- }
-
- template<class T>
- static inline void attrib(T x, T y, T z, T w)
- {
- if(attribbuf.check(4*sizeof(T)))
- {
- T *buf = (T *)attribbuf.pad(4*sizeof(T));
- buf[0] = x;
- buf[1] = y;
- buf[2] = z;
- buf[3] = w;
- }
- }
-
- template<size_t N, class T>
- static inline void attribv(const T *v)
- {
- attribbuf.put((const uchar *)v, N*sizeof(T));
- }
-
- #define GLE_ATTRIB(suffix, type) \
- static inline void attrib##suffix(type x) { attrib<type>(x); } \
- static inline void attrib##suffix(type x, type y) { attrib<type>(x, y); } \
- static inline void attrib##suffix(type x, type y, type z) { attrib<type>(x, y, z); } \
- static inline void attrib##suffix(type x, type y, type z, type w) { attrib<type>(x, y, z, w); }
-
- GLE_ATTRIB(f, float)
- GLE_ATTRIB(d, double)
- GLE_ATTRIB(b, char)
- GLE_ATTRIB(ub, uchar)
- GLE_ATTRIB(s, short)
- GLE_ATTRIB(us, ushort)
- GLE_ATTRIB(i, int)
- GLE_ATTRIB(ui, uint)
-
- static inline void attrib(const vec &v) { attribf(v.x, v.y, v.z); }
- static inline void attrib(const vec &v, float w) { attribf(v.x, v.y, v.z, w); }
- static inline void attrib(const vec2 &v) { attribf(v.x, v.y); }
- static inline void attrib(const vec4 &v) { attribf(v.x, v.y, v.z, v.w); }
- static inline void attrib(const ivec &v) { attribi(v.x, v.y, v.z); }
- static inline void attrib(const ivec &v, int w) { attribi(v.x, v.y, v.z, w); }
- static inline void attrib(const ivec2 &v) { attribi(v.x, v.y); }
- static inline void attrib(const ivec4 &v) { attribi(v.x, v.y, v.z, v.w); }
- static inline void attrib(const bvec &b) { attribub(b.x, b.y, b.z); }
- static inline void attrib(const bvec &b, uchar w) { attribub(b.x, b.y, b.z, w); }
- static inline void attrib(const bvec4 &b) { attribub(b.x, b.y, b.z, b.w); }
-
- extern void multidraw();
- extern int end();
-
- extern void enablequads();
- extern void disablequads();
- extern void drawquads(int offset, int count);
-
- extern void setup();
- extern void cleanup();
+ enum
+ {
+ ATTRIB_VERTEX = 0,
+ ATTRIB_COLOR = 1,
+ ATTRIB_TEXCOORD0 = 2,
+ ATTRIB_TEXCOORD1 = 3,
+ ATTRIB_NORMAL = 4,
+ ATTRIB_TANGENT = 5,
+ ATTRIB_BONEWEIGHT = 6,
+ ATTRIB_BONEINDEX = 7,
+ MAXATTRIBS = 8
+ };
+
+ extern const char * const attribnames[MAXATTRIBS];
+ extern ucharbuf attribbuf;
+
+ extern int enabled;
+ extern void forcedisable();
+ static inline void disable() { if(enabled) forcedisable(); }
+
+ extern void begin(GLenum mode);
+ extern void begin(GLenum mode, int numverts);
+ extern void defattribs(const char *fmt);
+ extern void defattrib(int type, int size, int format);
+
+ #define GLE_DEFATTRIB(name, type, defaultsize, defaultformat) \
+ static inline void def##name(int size = defaultsize, int format = defaultformat) { defattrib(type, size, format); }
+
+ GLE_DEFATTRIB(vertex, ATTRIB_VERTEX, 3, GL_FLOAT)
+ GLE_DEFATTRIB(color, ATTRIB_COLOR, 3, GL_FLOAT)
+ GLE_DEFATTRIB(texcoord0, ATTRIB_TEXCOORD0, 2, GL_FLOAT)
+ GLE_DEFATTRIB(texcoord1, ATTRIB_TEXCOORD1, 2, GL_FLOAT)
+ GLE_DEFATTRIB(normal, ATTRIB_NORMAL, 3, GL_FLOAT)
+ GLE_DEFATTRIB(tangent, ATTRIB_TANGENT, 4, GL_FLOAT)
+ GLE_DEFATTRIB(boneweight, ATTRIB_BONEWEIGHT, 4, GL_UNSIGNED_BYTE)
+ GLE_DEFATTRIB(boneindex, ATTRIB_BONEINDEX, 4, GL_UNSIGNED_BYTE)
+
+ #define GLE_INITATTRIB(name, index, suffix, type) \
+ static inline void name##suffix(type x) { glVertexAttrib1##suffix##_(index, x); } \
+ static inline void name##suffix(type x, type y) { glVertexAttrib2##suffix##_(index, x, y); } \
+ static inline void name##suffix(type x, type y, type z) { glVertexAttrib3##suffix##_(index, x, y, z); } \
+ static inline void name##suffix(type x, type y, type z, type w) { glVertexAttrib4##suffix##_(index, x, y, z, w); }
+ #define GLE_INITATTRIBF(name, index) \
+ GLE_INITATTRIB(name, index, f, float) \
+ static inline void name(const vec &v) { glVertexAttrib3fv_(index, v.v); } \
+ static inline void name(const vec &v, float w) { glVertexAttrib4f_(index, v.x, v.y, v.z, w); } \
+ static inline void name(const vec2 &v) { glVertexAttrib2fv_(index, v.v); } \
+ static inline void name(const vec4 &v) { glVertexAttrib4fv_(index, v.v); }
+ #define GLE_INITATTRIBN(name, index, suffix, type, defaultw) \
+ static inline void name##suffix(type x, type y, type z, type w = defaultw) { glVertexAttrib4N##suffix##_(index, x, y, z, w); }
+
+ GLE_INITATTRIBF(vertex, ATTRIB_VERTEX)
+ GLE_INITATTRIBF(color, ATTRIB_COLOR)
+ static inline void color(const bvec4 &v) { glVertexAttrib4Nubv_(ATTRIB_COLOR, v.v); }
+ static inline void color(const bvec &v, uchar alpha = 255) { color(bvec4(v, alpha)); }
+ static inline void colorub(uchar x, uchar y, uchar z, uchar w = 255) { color(bvec4(x, y, z, w)); }
+ GLE_INITATTRIBF(texcoord0, ATTRIB_TEXCOORD0)
+ GLE_INITATTRIBF(texcoord1, ATTRIB_TEXCOORD1)
+ static inline void normal(float x, float y, float z) { glVertexAttrib4f_(ATTRIB_NORMAL, x, y, z, 0.0f); }
+ static inline void normal(const vec &v) { glVertexAttrib4f_(ATTRIB_NORMAL, v.x, v.y, v.z, 0.0f); }
+ static inline void tangent(float x, float y, float z, float w = 1.0f) { glVertexAttrib4f_(ATTRIB_TANGENT, x, y, z, w); }
+ static inline void tangent(const vec &v, float w = 1.0f) { glVertexAttrib4f_(ATTRIB_TANGENT, v.x, v.y, v.z, w); }
+ static inline void tangent(const vec4 &v) { glVertexAttrib4fv_(ATTRIB_TANGENT, v.v); }
+
+ #define GLE_ATTRIBPOINTER(name, index, defaultnormalized, defaultsize, defaulttype, prepare) \
+ static inline void enable##name() { prepare; glEnableVertexAttribArray_(index); } \
+ static inline void disable##name() { glDisableVertexAttribArray_(index); } \
+ static inline void name##pointer(int stride, const void *data, GLenum type = defaulttype, int size = defaultsize, GLenum normalized = defaultnormalized) { \
+ prepare; \
+ glVertexAttribPointer_(index, size, type, normalized, stride, data); \
+ }
+
+ static inline void enableattrib(int index) { disable(); glEnableVertexAttribArray_(index); }
+ static inline void disableattrib(int index) { glDisableVertexAttribArray_(index); }
+ GLE_ATTRIBPOINTER(vertex, ATTRIB_VERTEX, GL_FALSE, 3, GL_FLOAT, disable())
+ GLE_ATTRIBPOINTER(color, ATTRIB_COLOR, GL_TRUE, 4, GL_UNSIGNED_BYTE, )
+ GLE_ATTRIBPOINTER(texcoord0, ATTRIB_TEXCOORD0, GL_FALSE, 2, GL_FLOAT, )
+ GLE_ATTRIBPOINTER(texcoord1, ATTRIB_TEXCOORD1, GL_FALSE, 2, GL_FLOAT, )
+ GLE_ATTRIBPOINTER(normal, ATTRIB_NORMAL, GL_TRUE, 3, GL_FLOAT, )
+ GLE_ATTRIBPOINTER(tangent, ATTRIB_TANGENT, GL_TRUE, 4, GL_FLOAT, )
+ GLE_ATTRIBPOINTER(boneweight, ATTRIB_BONEWEIGHT, GL_TRUE, 4, GL_UNSIGNED_BYTE, )
+ GLE_ATTRIBPOINTER(boneindex, ATTRIB_BONEINDEX, GL_FALSE, 4, GL_UNSIGNED_BYTE, )
+
+ static inline void bindebo(GLuint ebo) { disable(); glBindBuffer_(GL_ELEMENT_ARRAY_BUFFER, ebo); }
+ static inline void clearebo() { glBindBuffer_(GL_ELEMENT_ARRAY_BUFFER, 0); }
+ static inline void bindvbo(GLuint vbo) { disable(); glBindBuffer_(GL_ARRAY_BUFFER, vbo); }
+ static inline void clearvbo() { glBindBuffer_(GL_ARRAY_BUFFER, 0); }
+
+ template<class T>
+ static inline void attrib(T x)
+ {
+ if(attribbuf.check(sizeof(T)))
+ {
+ T *buf = (T *)attribbuf.pad(sizeof(T));
+ buf[0] = x;
+ }
+ }
+
+ template<class T>
+ static inline void attrib(T x, T y)
+ {
+ if(attribbuf.check(2*sizeof(T)))
+ {
+ T *buf = (T *)attribbuf.pad(2*sizeof(T));
+ buf[0] = x;
+ buf[1] = y;
+ }
+ }
+
+ template<class T>
+ static inline void attrib(T x, T y, T z)
+ {
+ if(attribbuf.check(3*sizeof(T)))
+ {
+ T *buf = (T *)attribbuf.pad(3*sizeof(T));
+ buf[0] = x;
+ buf[1] = y;
+ buf[2] = z;
+ }
+ }
+
+ template<class T>
+ static inline void attrib(T x, T y, T z, T w)
+ {
+ if(attribbuf.check(4*sizeof(T)))
+ {
+ T *buf = (T *)attribbuf.pad(4*sizeof(T));
+ buf[0] = x;
+ buf[1] = y;
+ buf[2] = z;
+ buf[3] = w;
+ }
+ }
+
+ template<size_t N, class T>
+ static inline void attribv(const T *v)
+ {
+ attribbuf.put((const uchar *)v, N*sizeof(T));
+ }
+
+ #define GLE_ATTRIB(suffix, type) \
+ static inline void attrib##suffix(type x) { attrib<type>(x); } \
+ static inline void attrib##suffix(type x, type y) { attrib<type>(x, y); } \
+ static inline void attrib##suffix(type x, type y, type z) { attrib<type>(x, y, z); } \
+ static inline void attrib##suffix(type x, type y, type z, type w) { attrib<type>(x, y, z, w); }
+
+ GLE_ATTRIB(f, float)
+ GLE_ATTRIB(d, double)
+ GLE_ATTRIB(b, char)
+ GLE_ATTRIB(ub, uchar)
+ GLE_ATTRIB(s, short)
+ GLE_ATTRIB(us, ushort)
+ GLE_ATTRIB(i, int)
+ GLE_ATTRIB(ui, uint)
+
+ static inline void attrib(const vec &v) { attribf(v.x, v.y, v.z); }
+ static inline void attrib(const vec &v, float w) { attribf(v.x, v.y, v.z, w); }
+ static inline void attrib(const vec2 &v) { attribf(v.x, v.y); }
+ static inline void attrib(const vec4 &v) { attribf(v.x, v.y, v.z, v.w); }
+ static inline void attrib(const ivec &v) { attribi(v.x, v.y, v.z); }
+ static inline void attrib(const ivec &v, int w) { attribi(v.x, v.y, v.z, w); }
+ static inline void attrib(const ivec2 &v) { attribi(v.x, v.y); }
+ static inline void attrib(const ivec4 &v) { attribi(v.x, v.y, v.z, v.w); }
+ static inline void attrib(const bvec &b) { attribub(b.x, b.y, b.z); }
+ static inline void attrib(const bvec &b, uchar w) { attribub(b.x, b.y, b.z, w); }
+ static inline void attrib(const bvec4 &b) { attribub(b.x, b.y, b.z, b.w); }
+
+ extern void multidraw();
+ extern int end();
+
+ extern void enablequads();
+ extern void disablequads();
+ extern void drawquads(int offset, int count);
+
+ extern void setup();
+ extern void cleanup();
}
diff --git a/src/shared/glexts.h b/src/shared/glexts.h
index 0b8e823..edc9e04 100644
--- a/src/shared/glexts.h
+++ b/src/shared/glexts.h
@@ -7,50 +7,49 @@
// OpenGL deprecated functionality
#ifndef GL_QUADS
-#define GL_QUADS 0x0007
+#define GL_QUADS 0x0007
#endif
#ifndef GL_ALPHA
-#define GL_ALPHA 0x1906
+#define GL_ALPHA 0x1906
#endif
#ifndef GL_ALPHA8
-#define GL_ALPHA8 0x803C
+#define GL_ALPHA8 0x803C
#endif
#ifndef GL_ALPHA16
-#define GL_ALPHA16 0x803E
+#define GL_ALPHA16 0x803E
#endif
#ifndef GL_COMPRESSED_ALPHA
-#define GL_COMPRESSED_ALPHA 0x84E9
+#define GL_COMPRESSED_ALPHA 0x84E9
#endif
#ifndef GL_LUMINANCE
-#define GL_LUMINANCE 0x1909
+#define GL_LUMINANCE 0x1909
#endif
#ifndef GL_LUMINANCE8
-#define GL_LUMINANCE8 0x8040
+#define GL_LUMINANCE8 0x8040
#endif
#ifndef GL_LUMINANCE16
-#define GL_LUMINANCE16 0x8042
+#define GL_LUMINANCE16 0x8042
#endif
#ifndef GL_COMPRESSED_LUMINANCE
-#define GL_COMPRESSED_LUMINANCE 0x84EA
+#define GL_COMPRESSED_LUMINANCE 0x84EA
#endif
#ifndef GL_LUMINANCE_ALPHA
-#define GL_LUMINANCE_ALPHA 0x190A
+#define GL_LUMINANCE_ALPHA 0x190A
#endif
#ifndef GL_LUMINANCE8_ALPHA8
-#define GL_LUMINANCE8_ALPHA8 0x8045
+#define GL_LUMINANCE8_ALPHA8 0x8045
#endif
#ifndef GL_LUMINANCE16_ALPHA16
-#define GL_LUMINANCE16_ALPHA16 0x8048
+#define GL_LUMINANCE16_ALPHA16 0x8048
#endif
#ifndef GL_COMPRESSED_LUMINANCE_ALPHA
#define GL_COMPRESSED_LUMINANCE_ALPHA 0x84EB
#endif
// OpenGL 1.3
-#ifndef WIN32
#define glActiveTexture_ glActiveTexture
#define glBlendEquation_ glBlendEquation
@@ -67,122 +66,7 @@
#define glGetCompressedTexImage_ glGetCompressedTexImage
#define glDrawRangeElements_ glDrawRangeElements
-#else
-extern PFNGLACTIVETEXTUREPROC glActiveTexture_;
-extern PFNGLBLENDEQUATIONPROC glBlendEquation_;
-extern PFNGLBLENDCOLORPROC glBlendColor_;
-
-extern PFNGLTEXIMAGE3DPROC glTexImage3D_;
-extern PFNGLTEXSUBIMAGE3DPROC glTexSubImage3D_;
-extern PFNGLCOPYTEXSUBIMAGE3DPROC glCopyTexSubImage3D_;
-
-extern PFNGLCOMPRESSEDTEXIMAGE3DPROC glCompressedTexImage3D_;
-extern PFNGLCOMPRESSEDTEXIMAGE2DPROC glCompressedTexImage2D_;
-extern PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC glCompressedTexSubImage3D_;
-extern PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glCompressedTexSubImage2D_;
-extern PFNGLGETCOMPRESSEDTEXIMAGEPROC glGetCompressedTexImage_;
-
-extern PFNGLDRAWRANGEELEMENTSPROC glDrawRangeElements_;
-#endif
-
-// OpenGL 2.0
-#ifdef __APPLE__
-#define glMultiDrawArrays_ glMultiDrawArrays
-#define glMultiDrawElements_ glMultiDrawElements
-
-#define glBlendFuncSeparate_ glBlendFuncSeparate
-#define glBlendEquationSeparate_ glBlendEquationSeparate
-#define glStencilOpSeparate_ glStencilOpSeparate
-#define glStencilFuncSeparate_ glStencilFuncSeparate
-#define glStencilMaskSeparate_ glStencilMaskSeparate
-
-#define glGenBuffers_ glGenBuffers
-#define glBindBuffer_ glBindBuffer
-#define glMapBuffer_ glMapBuffer
-#define glUnmapBuffer_ glUnmapBuffer
-#define glBufferData_ glBufferData
-#define glBufferSubData_ glBufferSubData
-#define glDeleteBuffers_ glDeleteBuffers
-#define glGetBufferSubData_ glGetBufferSubData
-
-#define glGenQueries_ glGenQueries
-#define glDeleteQueries_ glDeleteQueries
-#define glBeginQuery_ glBeginQuery
-#define glEndQuery_ glEndQuery
-#define glGetQueryiv_ glGetQueryiv
-#define glGetQueryObjectiv_ glGetQueryObjectiv
-#define glGetQueryObjectuiv_ glGetQueryObjectuiv
-
-#define glCreateProgram_ glCreateProgram
-#define glDeleteProgram_ glDeleteProgram
-#define glUseProgram_ glUseProgram
-#define glCreateShader_ glCreateShader
-#define glDeleteShader_ glDeleteShader
-#define glShaderSource_ glShaderSource
-#define glCompileShader_ glCompileShader
-#define glGetShaderiv_ glGetShaderiv
-#define glGetProgramiv_ glGetProgramiv
-#define glAttachShader_ glAttachShader
-#define glGetProgramInfoLog_ glGetProgramInfoLog
-#define glGetShaderInfoLog_ glGetShaderInfoLog
-#define glLinkProgram_ glLinkProgram
-#define glGetUniformLocation_ glGetUniformLocation
-#define glUniform1f_ glUniform1f
-#define glUniform2f_ glUniform2f
-#define glUniform3f_ glUniform3f
-#define glUniform4f_ glUniform4f
-#define glUniform1fv_ glUniform1fv
-#define glUniform2fv_ glUniform2fv
-#define glUniform3fv_ glUniform3fv
-#define glUniform4fv_ glUniform4fv
-#define glUniform1i_ glUniform1i
-#define glUniform2i_ glUniform2i
-#define glUniform3i_ glUniform3i
-#define glUniform4i_ glUniform4i
-#define glUniform1iv_ glUniform1iv
-#define glUniform2iv_ glUniform2iv
-#define glUniform3iv_ glUniform3iv
-#define glUniform4iv_ glUniform4iv
-#define glUniformMatrix2fv_ glUniformMatrix2fv
-#define glUniformMatrix3fv_ glUniformMatrix3fv
-#define glUniformMatrix4fv_ glUniformMatrix4fv
-#define glBindAttribLocation_ glBindAttribLocation
-#define glGetActiveUniform_ glGetActiveUniform
-#define glEnableVertexAttribArray_ glEnableVertexAttribArray
-#define glDisableVertexAttribArray_ glDisableVertexAttribArray
-
-#define glVertexAttrib1f_ glVertexAttrib1f
-#define glVertexAttrib1fv_ glVertexAttrib1fv
-#define glVertexAttrib1s_ glVertexAttrib1s
-#define glVertexAttrib1sv_ glVertexAttrib1sv
-#define glVertexAttrib2f_ glVertexAttrib2f
-#define glVertexAttrib2fv_ glVertexAttrib2fv
-#define glVertexAttrib2s_ glVertexAttrib2s
-#define glVertexAttrib2sv_ glVertexAttrib2sv
-#define glVertexAttrib3f_ glVertexAttrib3f
-#define glVertexAttrib3fv_ glVertexAttrib3fv
-#define glVertexAttrib3s_ glVertexAttrib3s
-#define glVertexAttrib3sv_ glVertexAttrib3sv
-#define glVertexAttrib4f_ glVertexAttrib4f
-#define glVertexAttrib4fv_ glVertexAttrib4fv
-#define glVertexAttrib4s_ glVertexAttrib4s
-#define glVertexAttrib4sv_ glVertexAttrib4sv
-#define glVertexAttrib4bv_ glVertexAttrib4bv
-#define glVertexAttrib4iv_ glVertexAttrib4iv
-#define glVertexAttrib4ubv_ glVertexAttrib4ubv
-#define glVertexAttrib4uiv_ glVertexAttrib4uiv
-#define glVertexAttrib4usv_ glVertexAttrib4usv
-#define glVertexAttrib4Nbv_ glVertexAttrib4Nbv
-#define glVertexAttrib4Niv_ glVertexAttrib4Niv
-#define glVertexAttrib4Nub_ glVertexAttrib4Nub
-#define glVertexAttrib4Nubv_ glVertexAttrib4Nubv
-#define glVertexAttrib4Nuiv_ glVertexAttrib4Nuiv
-#define glVertexAttrib4Nusv_ glVertexAttrib4Nusv
-#define glVertexAttribPointer_ glVertexAttribPointer
-
-#define glDrawBuffers_ glDrawBuffers
-#else
extern PFNGLMULTIDRAWARRAYSPROC glMultiDrawArrays_;
extern PFNGLMULTIDRAWELEMENTSPROC glMultiDrawElements_;
@@ -192,102 +76,101 @@ extern PFNGLSTENCILOPSEPARATEPROC glStencilOpSeparate_;
extern PFNGLSTENCILFUNCSEPARATEPROC glStencilFuncSeparate_;
extern PFNGLSTENCILMASKSEPARATEPROC glStencilMaskSeparate_;
-extern PFNGLGENBUFFERSPROC glGenBuffers_;
-extern PFNGLBINDBUFFERPROC glBindBuffer_;
-extern PFNGLMAPBUFFERPROC glMapBuffer_;
-extern PFNGLUNMAPBUFFERPROC glUnmapBuffer_;
-extern PFNGLBUFFERDATAPROC glBufferData_;
-extern PFNGLBUFFERSUBDATAPROC glBufferSubData_;
-extern PFNGLDELETEBUFFERSPROC glDeleteBuffers_;
+extern PFNGLGENBUFFERSPROC glGenBuffers_;
+extern PFNGLBINDBUFFERPROC glBindBuffer_;
+extern PFNGLMAPBUFFERPROC glMapBuffer_;
+extern PFNGLUNMAPBUFFERPROC glUnmapBuffer_;
+extern PFNGLBUFFERDATAPROC glBufferData_;
+extern PFNGLBUFFERSUBDATAPROC glBufferSubData_;
+extern PFNGLDELETEBUFFERSPROC glDeleteBuffers_;
extern PFNGLGETBUFFERSUBDATAPROC glGetBufferSubData_;
-extern PFNGLGENQUERIESPROC glGenQueries_;
-extern PFNGLDELETEQUERIESPROC glDeleteQueries_;
-extern PFNGLBEGINQUERYPROC glBeginQuery_;
-extern PFNGLENDQUERYPROC glEndQuery_;
-extern PFNGLGETQUERYIVPROC glGetQueryiv_;
+extern PFNGLGENQUERIESPROC glGenQueries_;
+extern PFNGLDELETEQUERIESPROC glDeleteQueries_;
+extern PFNGLBEGINQUERYPROC glBeginQuery_;
+extern PFNGLENDQUERYPROC glEndQuery_;
+extern PFNGLGETQUERYIVPROC glGetQueryiv_;
extern PFNGLGETQUERYOBJECTIVPROC glGetQueryObjectiv_;
extern PFNGLGETQUERYOBJECTUIVPROC glGetQueryObjectuiv_;
-extern PFNGLCREATEPROGRAMPROC glCreateProgram_;
-extern PFNGLDELETEPROGRAMPROC glDeleteProgram_;
-extern PFNGLUSEPROGRAMPROC glUseProgram_;
-extern PFNGLCREATESHADERPROC glCreateShader_;
-extern PFNGLDELETESHADERPROC glDeleteShader_;
-extern PFNGLSHADERSOURCEPROC glShaderSource_;
-extern PFNGLCOMPILESHADERPROC glCompileShader_;
-extern PFNGLGETSHADERIVPROC glGetShaderiv_;
-extern PFNGLGETPROGRAMIVPROC glGetProgramiv_;
-extern PFNGLATTACHSHADERPROC glAttachShader_;
-extern PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog_;
-extern PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog_;
-extern PFNGLLINKPROGRAMPROC glLinkProgram_;
-extern PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation_;
-extern PFNGLUNIFORM1FPROC glUniform1f_;
-extern PFNGLUNIFORM2FPROC glUniform2f_;
-extern PFNGLUNIFORM3FPROC glUniform3f_;
-extern PFNGLUNIFORM4FPROC glUniform4f_;
-extern PFNGLUNIFORM1FVPROC glUniform1fv_;
-extern PFNGLUNIFORM2FVPROC glUniform2fv_;
-extern PFNGLUNIFORM3FVPROC glUniform3fv_;
-extern PFNGLUNIFORM4FVPROC glUniform4fv_;
-extern PFNGLUNIFORM1IPROC glUniform1i_;
-extern PFNGLUNIFORM2IPROC glUniform2i_;
-extern PFNGLUNIFORM3IPROC glUniform3i_;
-extern PFNGLUNIFORM4IPROC glUniform4i_;
-extern PFNGLUNIFORM1IVPROC glUniform1iv_;
-extern PFNGLUNIFORM2IVPROC glUniform2iv_;
-extern PFNGLUNIFORM3IVPROC glUniform3iv_;
-extern PFNGLUNIFORM4IVPROC glUniform4iv_;
-extern PFNGLUNIFORMMATRIX2FVPROC glUniformMatrix2fv_;
-extern PFNGLUNIFORMMATRIX3FVPROC glUniformMatrix3fv_;
-extern PFNGLUNIFORMMATRIX4FVPROC glUniformMatrix4fv_;
-extern PFNGLBINDATTRIBLOCATIONPROC glBindAttribLocation_;
-extern PFNGLGETACTIVEUNIFORMPROC glGetActiveUniform_;
+extern PFNGLCREATEPROGRAMPROC glCreateProgram_;
+extern PFNGLDELETEPROGRAMPROC glDeleteProgram_;
+extern PFNGLUSEPROGRAMPROC glUseProgram_;
+extern PFNGLCREATESHADERPROC glCreateShader_;
+extern PFNGLDELETESHADERPROC glDeleteShader_;
+extern PFNGLSHADERSOURCEPROC glShaderSource_;
+extern PFNGLCOMPILESHADERPROC glCompileShader_;
+extern PFNGLGETSHADERIVPROC glGetShaderiv_;
+extern PFNGLGETPROGRAMIVPROC glGetProgramiv_;
+extern PFNGLATTACHSHADERPROC glAttachShader_;
+extern PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog_;
+extern PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog_;
+extern PFNGLLINKPROGRAMPROC glLinkProgram_;
+extern PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation_;
+extern PFNGLUNIFORM1FPROC glUniform1f_;
+extern PFNGLUNIFORM2FPROC glUniform2f_;
+extern PFNGLUNIFORM3FPROC glUniform3f_;
+extern PFNGLUNIFORM4FPROC glUniform4f_;
+extern PFNGLUNIFORM1FVPROC glUniform1fv_;
+extern PFNGLUNIFORM2FVPROC glUniform2fv_;
+extern PFNGLUNIFORM3FVPROC glUniform3fv_;
+extern PFNGLUNIFORM4FVPROC glUniform4fv_;
+extern PFNGLUNIFORM1IPROC glUniform1i_;
+extern PFNGLUNIFORM2IPROC glUniform2i_;
+extern PFNGLUNIFORM3IPROC glUniform3i_;
+extern PFNGLUNIFORM4IPROC glUniform4i_;
+extern PFNGLUNIFORM1IVPROC glUniform1iv_;
+extern PFNGLUNIFORM2IVPROC glUniform2iv_;
+extern PFNGLUNIFORM3IVPROC glUniform3iv_;
+extern PFNGLUNIFORM4IVPROC glUniform4iv_;
+extern PFNGLUNIFORMMATRIX2FVPROC glUniformMatrix2fv_;
+extern PFNGLUNIFORMMATRIX3FVPROC glUniformMatrix3fv_;
+extern PFNGLUNIFORMMATRIX4FVPROC glUniformMatrix4fv_;
+extern PFNGLBINDATTRIBLOCATIONPROC glBindAttribLocation_;
+extern PFNGLGETACTIVEUNIFORMPROC glGetActiveUniform_;
extern PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray_;
extern PFNGLDISABLEVERTEXATTRIBARRAYPROC glDisableVertexAttribArray_;
-extern PFNGLVERTEXATTRIB1FPROC glVertexAttrib1f_;
-extern PFNGLVERTEXATTRIB1FVPROC glVertexAttrib1fv_;
-extern PFNGLVERTEXATTRIB1SPROC glVertexAttrib1s_;
-extern PFNGLVERTEXATTRIB1SVPROC glVertexAttrib1sv_;
-extern PFNGLVERTEXATTRIB2FPROC glVertexAttrib2f_;
-extern PFNGLVERTEXATTRIB2FVPROC glVertexAttrib2fv_;
-extern PFNGLVERTEXATTRIB2SPROC glVertexAttrib2s_;
-extern PFNGLVERTEXATTRIB2SVPROC glVertexAttrib2sv_;
-extern PFNGLVERTEXATTRIB3FPROC glVertexAttrib3f_;
-extern PFNGLVERTEXATTRIB3FVPROC glVertexAttrib3fv_;
-extern PFNGLVERTEXATTRIB3SPROC glVertexAttrib3s_;
-extern PFNGLVERTEXATTRIB3SVPROC glVertexAttrib3sv_;
-extern PFNGLVERTEXATTRIB4FPROC glVertexAttrib4f_;
-extern PFNGLVERTEXATTRIB4FVPROC glVertexAttrib4fv_;
-extern PFNGLVERTEXATTRIB4SPROC glVertexAttrib4s_;
-extern PFNGLVERTEXATTRIB4SVPROC glVertexAttrib4sv_;
-extern PFNGLVERTEXATTRIB4BVPROC glVertexAttrib4bv_;
-extern PFNGLVERTEXATTRIB4IVPROC glVertexAttrib4iv_;
-extern PFNGLVERTEXATTRIB4UBVPROC glVertexAttrib4ubv_;
-extern PFNGLVERTEXATTRIB4UIVPROC glVertexAttrib4uiv_;
-extern PFNGLVERTEXATTRIB4USVPROC glVertexAttrib4usv_;
-extern PFNGLVERTEXATTRIB4NBVPROC glVertexAttrib4Nbv_;
-extern PFNGLVERTEXATTRIB4NIVPROC glVertexAttrib4Niv_;
-extern PFNGLVERTEXATTRIB4NUBPROC glVertexAttrib4Nub_;
-extern PFNGLVERTEXATTRIB4NUBVPROC glVertexAttrib4Nubv_;
-extern PFNGLVERTEXATTRIB4NUIVPROC glVertexAttrib4Nuiv_;
-extern PFNGLVERTEXATTRIB4NUSVPROC glVertexAttrib4Nusv_;
-extern PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer_;
+extern PFNGLVERTEXATTRIB1FPROC glVertexAttrib1f_;
+extern PFNGLVERTEXATTRIB1FVPROC glVertexAttrib1fv_;
+extern PFNGLVERTEXATTRIB1SPROC glVertexAttrib1s_;
+extern PFNGLVERTEXATTRIB1SVPROC glVertexAttrib1sv_;
+extern PFNGLVERTEXATTRIB2FPROC glVertexAttrib2f_;
+extern PFNGLVERTEXATTRIB2FVPROC glVertexAttrib2fv_;
+extern PFNGLVERTEXATTRIB2SPROC glVertexAttrib2s_;
+extern PFNGLVERTEXATTRIB2SVPROC glVertexAttrib2sv_;
+extern PFNGLVERTEXATTRIB3FPROC glVertexAttrib3f_;
+extern PFNGLVERTEXATTRIB3FVPROC glVertexAttrib3fv_;
+extern PFNGLVERTEXATTRIB3SPROC glVertexAttrib3s_;
+extern PFNGLVERTEXATTRIB3SVPROC glVertexAttrib3sv_;
+extern PFNGLVERTEXATTRIB4FPROC glVertexAttrib4f_;
+extern PFNGLVERTEXATTRIB4FVPROC glVertexAttrib4fv_;
+extern PFNGLVERTEXATTRIB4SPROC glVertexAttrib4s_;
+extern PFNGLVERTEXATTRIB4SVPROC glVertexAttrib4sv_;
+extern PFNGLVERTEXATTRIB4BVPROC glVertexAttrib4bv_;
+extern PFNGLVERTEXATTRIB4IVPROC glVertexAttrib4iv_;
+extern PFNGLVERTEXATTRIB4UBVPROC glVertexAttrib4ubv_;
+extern PFNGLVERTEXATTRIB4UIVPROC glVertexAttrib4uiv_;
+extern PFNGLVERTEXATTRIB4USVPROC glVertexAttrib4usv_;
+extern PFNGLVERTEXATTRIB4NBVPROC glVertexAttrib4Nbv_;
+extern PFNGLVERTEXATTRIB4NIVPROC glVertexAttrib4Niv_;
+extern PFNGLVERTEXATTRIB4NUBPROC glVertexAttrib4Nub_;
+extern PFNGLVERTEXATTRIB4NUBVPROC glVertexAttrib4Nubv_;
+extern PFNGLVERTEXATTRIB4NUIVPROC glVertexAttrib4Nuiv_;
+extern PFNGLVERTEXATTRIB4NUSVPROC glVertexAttrib4Nusv_;
+extern PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer_;
extern PFNGLDRAWBUFFERSPROC glDrawBuffers_;
-#endif
#ifndef GL_VERSION_2_1
#define GL_VERSION_2_1 1
-#define GL_PIXEL_PACK_BUFFER 0x88EB
-#define GL_PIXEL_UNPACK_BUFFER 0x88EC
+#define GL_PIXEL_PACK_BUFFER 0x88EB
+#define GL_PIXEL_UNPACK_BUFFER 0x88EC
#endif
#ifndef GL_EXT_texture_filter_anisotropic
#define GL_EXT_texture_filter_anisotropic 1
-#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
+#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
#endif
@@ -301,20 +184,20 @@ extern PFNGLDRAWBUFFERSPROC glDrawBuffers_;
#ifndef GL_ARB_framebuffer_object
#define GL_ARB_framebuffer_object 1
-#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A
-#define GL_DEPTH_STENCIL 0x84F9
-#define GL_UNSIGNED_INT_24_8 0x84FA
-#define GL_DEPTH24_STENCIL8 0x88F0
-#define GL_FRAMEBUFFER_BINDING 0x8CA6
-#define GL_READ_FRAMEBUFFER 0x8CA8
-#define GL_DRAW_FRAMEBUFFER 0x8CA9
-#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
-#define GL_COLOR_ATTACHMENT0 0x8CE0
-#define GL_COLOR_ATTACHMENT1 0x8CE1
-#define GL_DEPTH_ATTACHMENT 0x8D00
-#define GL_STENCIL_ATTACHMENT 0x8D20
-#define GL_FRAMEBUFFER 0x8D40
-#define GL_RENDERBUFFER 0x8D41
+#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A
+#define GL_DEPTH_STENCIL 0x84F9
+#define GL_UNSIGNED_INT_24_8 0x84FA
+#define GL_DEPTH24_STENCIL8 0x88F0
+#define GL_FRAMEBUFFER_BINDING 0x8CA6
+#define GL_READ_FRAMEBUFFER 0x8CA8
+#define GL_DRAW_FRAMEBUFFER 0x8CA9
+#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
+#define GL_COLOR_ATTACHMENT0 0x8CE0
+#define GL_COLOR_ATTACHMENT1 0x8CE1
+#define GL_DEPTH_ATTACHMENT 0x8D00
+#define GL_STENCIL_ATTACHMENT 0x8D20
+#define GL_FRAMEBUFFER 0x8D40
+#define GL_RENDERBUFFER 0x8D41
typedef void (APIENTRYP PFNGLBINDRENDERBUFFERPROC) (GLenum target, GLuint renderbuffer);
typedef void (APIENTRYP PFNGLDELETERENDERBUFFERSPROC) (GLsizei n, const GLuint *renderbuffers);
typedef void (APIENTRYP PFNGLGENRENDERBUFFERSPROC) (GLsizei n, GLuint *renderbuffers);
@@ -330,95 +213,95 @@ typedef void (APIENTRYP PFNGLBLITFRAMEBUFFERPROC) (GLint srcX0, GLint srcY0, GLi
#endif
// GL_EXT_framebuffer_object
-extern PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer_;
-extern PFNGLDELETERENDERBUFFERSPROC glDeleteRenderbuffers_;
-extern PFNGLGENFRAMEBUFFERSPROC glGenRenderbuffers_;
-extern PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage_;
+extern PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer_;
+extern PFNGLDELETERENDERBUFFERSPROC glDeleteRenderbuffers_;
+extern PFNGLGENFRAMEBUFFERSPROC glGenRenderbuffers_;
+extern PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage_;
extern PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus_;
-extern PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer_;
-extern PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers_;
-extern PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers_;
-extern PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D_;
+extern PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer_;
+extern PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers_;
+extern PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers_;
+extern PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D_;
extern PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer_;
-extern PFNGLGENERATEMIPMAPPROC glGenerateMipmap_;
+extern PFNGLGENERATEMIPMAPPROC glGenerateMipmap_;
// GL_EXT_framebuffer_blit
-extern PFNGLBLITFRAMEBUFFERPROC glBlitFramebuffer_;
+extern PFNGLBLITFRAMEBUFFERPROC glBlitFramebuffer_;
#ifndef GL_ARB_texture_rg
#define GL_ARB_texture_rg 1
-#define GL_RG 0x8227
-#define GL_R8 0x8229
-#define GL_R16 0x822A
-#define GL_RG8 0x822B
-#define GL_RG16 0x822C
-#define GL_R16F 0x822D
-#define GL_R32F 0x822E
-#define GL_RG16F 0x822F
-#define GL_RG32F 0x8230
+#define GL_RG 0x8227
+#define GL_R8 0x8229
+#define GL_R16 0x822A
+#define GL_RG8 0x822B
+#define GL_RG16 0x822C
+#define GL_R16F 0x822D
+#define GL_R32F 0x822E
+#define GL_RG16F 0x822F
+#define GL_RG32F 0x8230
#endif
#ifndef GL_EXT_texture_compression_latc
#define GL_EXT_texture_compression_latc 1
-#define GL_COMPRESSED_LUMINANCE_LATC1_EXT 0x8C70
-#define GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT 0x8C72
+#define GL_COMPRESSED_LUMINANCE_LATC1_EXT 0x8C70
+#define GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT 0x8C72
#endif
#ifndef GL_ARB_texture_compression_rgtc
#define GL_ARB_texture_compression_rgtc 1
-#define GL_COMPRESSED_RED_RGTC1 0x8DBB
-#define GL_COMPRESSED_RG_RGTC2 0x8DBD
+#define GL_COMPRESSED_RED_RGTC1 0x8DBB
+#define GL_COMPRESSED_RG_RGTC2 0x8DBD
#endif
#ifndef GL_ARB_map_buffer_range
#define GL_ARB_map_buffer_range 1
-#define GL_MAP_READ_BIT 0x0001
-#define GL_MAP_WRITE_BIT 0x0002
-#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004
-#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008
-#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010
-#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020
+#define GL_MAP_READ_BIT 0x0001
+#define GL_MAP_WRITE_BIT 0x0002
+#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004
+#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008
+#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010
+#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020
typedef GLvoid* (APIENTRYP PFNGLMAPBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
typedef void (APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length);
#endif
-extern PFNGLMAPBUFFERRANGEPROC glMapBufferRange_;
+extern PFNGLMAPBUFFERRANGEPROC glMapBufferRange_;
extern PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange_;
#ifndef GL_ARB_uniform_buffer_object
#define GL_ARB_uniform_buffer_object 1
-#define GL_UNIFORM_BUFFER 0x8A11
-#define GL_UNIFORM_BUFFER_BINDING 0x8A28
-#define GL_UNIFORM_BUFFER_START 0x8A29
-#define GL_UNIFORM_BUFFER_SIZE 0x8A2A
-#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B
-#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS 0x8A2C
-#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D
-#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E
-#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F
-#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30
+#define GL_UNIFORM_BUFFER 0x8A11
+#define GL_UNIFORM_BUFFER_BINDING 0x8A28
+#define GL_UNIFORM_BUFFER_START 0x8A29
+#define GL_UNIFORM_BUFFER_SIZE 0x8A2A
+#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B
+#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS 0x8A2C
+#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D
+#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E
+#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F
+#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30
#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31
#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS 0x8A32
#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33
#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34
#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35
-#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36
-#define GL_UNIFORM_TYPE 0x8A37
-#define GL_UNIFORM_SIZE 0x8A38
-#define GL_UNIFORM_NAME_LENGTH 0x8A39
-#define GL_UNIFORM_BLOCK_INDEX 0x8A3A
-#define GL_UNIFORM_OFFSET 0x8A3B
-#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C
-#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D
-#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E
-#define GL_UNIFORM_BLOCK_BINDING 0x8A3F
-#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40
-#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41
+#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36
+#define GL_UNIFORM_TYPE 0x8A37
+#define GL_UNIFORM_SIZE 0x8A38
+#define GL_UNIFORM_NAME_LENGTH 0x8A39
+#define GL_UNIFORM_BLOCK_INDEX 0x8A3A
+#define GL_UNIFORM_OFFSET 0x8A3B
+#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C
+#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D
+#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E
+#define GL_UNIFORM_BLOCK_BINDING 0x8A3F
+#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40
+#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41
#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42
#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43
#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44
#define GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER 0x8A45
#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46
-#define GL_INVALID_INDEX 0xFFFFFFFFu
+#define GL_INVALID_INDEX 0xFFFFFFFFu
typedef void (APIENTRYP PFNGLGETUNIFORMINDICESPROC) (GLuint program, GLsizei uniformCount, const GLchar* *uniformNames, GLuint *uniformIndices);
typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMSIVPROC) (GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params);
typedef GLuint (APIENTRYP PFNGLGETUNIFORMBLOCKINDEXPROC) (GLuint program, const GLchar *uniformBlockName);
@@ -426,25 +309,25 @@ typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKIVPROC) (GLuint program, GLuin
typedef void (APIENTRYP PFNGLUNIFORMBLOCKBINDINGPROC) (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
#endif
#ifndef GL_INVALID_INDEX
-#define GL_INVALID_INDEX 0xFFFFFFFFu
+#define GL_INVALID_INDEX 0xFFFFFFFFu
#endif
-extern PFNGLGETUNIFORMINDICESPROC glGetUniformIndices_;
-extern PFNGLGETACTIVEUNIFORMSIVPROC glGetActiveUniformsiv_;
-extern PFNGLGETUNIFORMBLOCKINDEXPROC glGetUniformBlockIndex_;
+extern PFNGLGETUNIFORMINDICESPROC glGetUniformIndices_;
+extern PFNGLGETACTIVEUNIFORMSIVPROC glGetActiveUniformsiv_;
+extern PFNGLGETUNIFORMBLOCKINDEXPROC glGetUniformBlockIndex_;
extern PFNGLGETACTIVEUNIFORMBLOCKIVPROC glGetActiveUniformBlockiv_;
-extern PFNGLUNIFORMBLOCKBINDINGPROC glUniformBlockBinding_;
+extern PFNGLUNIFORMBLOCKBINDINGPROC glUniformBlockBinding_;
#ifndef GL_VERSION_3_0
#define GL_VERSION_3_0 1
-#define GL_NUM_EXTENSIONS 0x821D
-#define GL_COMPARE_REF_TO_TEXTURE 0x884E
-#define GL_MAX_VARYING_COMPONENTS 0x8B4B
-#define GL_RGBA32F 0x8814
-#define GL_RGB32F 0x8815
-#define GL_RGBA16F 0x881A
-#define GL_RGB16F 0x881B
-#define GL_COMPRESSED_RED 0x8225
-#define GL_COMPRESSED_RG 0x8226
+#define GL_NUM_EXTENSIONS 0x821D
+#define GL_COMPARE_REF_TO_TEXTURE 0x884E
+#define GL_MAX_VARYING_COMPONENTS 0x8B4B
+#define GL_RGBA32F 0x8814
+#define GL_RGB32F 0x8815
+#define GL_RGBA16F 0x881A
+#define GL_RGB16F 0x881B
+#define GL_COMPRESSED_RED 0x8225
+#define GL_COMPRESSED_RG 0x8226
typedef void (APIENTRYP PFNGLBINDBUFFERRANGEPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
typedef void (APIENTRYP PFNGLBINDBUFFERBASEPROC) (GLenum target, GLuint index, GLuint buffer);
typedef void (APIENTRYP PFNGLBINDFRAGDATALOCATIONPROC) (GLuint program, GLuint color, const GLchar *name);
@@ -454,34 +337,34 @@ typedef void (APIENTRYP PFNGLBINDBUFFERRANGEPROC) (GLenum target, GLuint index,
typedef void (APIENTRYP PFNGLBINDBUFFERBASEPROC) (GLenum target, GLuint index, GLuint buffer);
#endif
-extern PFNGLGETSTRINGIPROC glGetStringi_;
+extern PFNGLGETSTRINGIPROC glGetStringi_;
extern PFNGLBINDFRAGDATALOCATIONPROC glBindFragDataLocation_;
-extern PFNGLBINDBUFFERBASEPROC glBindBufferBase_;
-extern PFNGLBINDBUFFERRANGEPROC glBindBufferRange_;
+extern PFNGLBINDBUFFERBASEPROC glBindBufferBase_;
+extern PFNGLBINDBUFFERRANGEPROC glBindBufferRange_;
#ifndef GL_VERSION_3_1
#define GL_VERSION_3_1 1
-#define GL_TEXTURE_RECTANGLE 0x84F5
+#define GL_TEXTURE_RECTANGLE 0x84F5
#endif
#ifndef GL_ARB_vertex_array_object
#define GL_ARB_vertex_array_object 1
-#define GL_VERTEX_ARRAY_BINDING 0x85B5
+#define GL_VERTEX_ARRAY_BINDING 0x85B5
typedef void (APIENTRYP PFNGLBINDVERTEXARRAYPROC) (GLuint array);
typedef void (APIENTRYP PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint *arrays);
typedef void (APIENTRYP PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint *arrays);
typedef GLboolean (APIENTRYP PFNGLISVERTEXARRAYPROC) (GLuint array);
#endif
-extern PFNGLBINDVERTEXARRAYPROC glBindVertexArray_;
+extern PFNGLBINDVERTEXARRAYPROC glBindVertexArray_;
extern PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays_;
-extern PFNGLGENVERTEXARRAYSPROC glGenVertexArrays_;
-extern PFNGLISVERTEXARRAYPROC glIsVertexArray_;
+extern PFNGLGENVERTEXARRAYSPROC glGenVertexArrays_;
+extern PFNGLISVERTEXARRAYPROC glIsVertexArray_;
#ifndef GL_ARB_texture_swizzle
#define GL_ARB_texture_swizzle 1
-#define GL_TEXTURE_SWIZZLE_R 0x8E42
-#define GL_TEXTURE_SWIZZLE_G 0x8E43
-#define GL_TEXTURE_SWIZZLE_B 0x8E44
-#define GL_TEXTURE_SWIZZLE_A 0x8E45
-#define GL_TEXTURE_SWIZZLE_RGBA 0x8E46
+#define GL_TEXTURE_SWIZZLE_R 0x8E42
+#define GL_TEXTURE_SWIZZLE_G 0x8E43
+#define GL_TEXTURE_SWIZZLE_B 0x8E44
+#define GL_TEXTURE_SWIZZLE_A 0x8E45
+#define GL_TEXTURE_SWIZZLE_RGBA 0x8E46
#endif
diff --git a/src/shared/iengine.h b/src/shared/iengine.h
index 80bc9c5..bc2f7a9 100644
--- a/src/shared/iengine.h
+++ b/src/shared/iengine.h
@@ -1,38 +1,38 @@
// the interface the game uses to access the engine
-extern int curtime; // current frame time
-extern int lastmillis; // last time
-extern int elapsedtime; // elapsed frame time
-extern int totalmillis; // total elapsed time
+extern int curtime; // current frame time
+extern int lastmillis; // last time
+extern int elapsedtime; // elapsed frame time
+extern int totalmillis; // total elapsed time
extern uint totalsecs;
extern int gamespeed, paused;
enum
{
- MATF_INDEX_SHIFT = 0,
- MATF_VOLUME_SHIFT = 2,
- MATF_CLIP_SHIFT = 5,
- MATF_FLAG_SHIFT = 8,
-
- MATF_INDEX = 3 << MATF_INDEX_SHIFT,
- MATF_VOLUME = 7 << MATF_VOLUME_SHIFT,
- MATF_CLIP = 7 << MATF_CLIP_SHIFT,
- MATF_FLAGS = 0xFF << MATF_FLAG_SHIFT
+ MATF_INDEX_SHIFT = 0,
+ MATF_VOLUME_SHIFT = 2,
+ MATF_CLIP_SHIFT = 5,
+ MATF_FLAG_SHIFT = 8,
+
+ MATF_INDEX = 3 << MATF_INDEX_SHIFT,
+ MATF_VOLUME = 7 << MATF_VOLUME_SHIFT,
+ MATF_CLIP = 7 << MATF_CLIP_SHIFT,
+ MATF_FLAGS = 0xFF << MATF_FLAG_SHIFT
};
enum // cube empty-space materials
{
- MAT_AIR = 0, // the default, fill the empty space with air
- MAT_WATER = 1 << MATF_VOLUME_SHIFT, // fill with water, showing waves at the surface
- MAT_LAVA = 2 << MATF_VOLUME_SHIFT, // fill with lava
- MAT_GLASS = 3 << MATF_VOLUME_SHIFT, // behaves like clip but is blended blueish
+ MAT_AIR = 0, // the default, fill the empty space with air
+ MAT_WATER = 1 << MATF_VOLUME_SHIFT, // fill with water, showing waves at the surface
+ MAT_LAVA = 2 << MATF_VOLUME_SHIFT, // fill with lava
+ MAT_GLASS = 3 << MATF_VOLUME_SHIFT, // behaves like clip but is blended blueish
- MAT_NOCLIP = 1 << MATF_CLIP_SHIFT, // collisions always treat cube as empty
- MAT_CLIP = 2 << MATF_CLIP_SHIFT, // collisions always treat cube as solid
- MAT_GAMECLIP = 3 << MATF_CLIP_SHIFT, // game specific clip material
+ MAT_NOCLIP = 1 << MATF_CLIP_SHIFT, // collisions always treat cube as empty
+ MAT_CLIP = 2 << MATF_CLIP_SHIFT, // collisions always treat cube as solid
+ MAT_GAMECLIP = 3 << MATF_CLIP_SHIFT, // game specific clip material
- MAT_DEATH = 1 << MATF_FLAG_SHIFT, // force player suicide
- MAT_ALPHA = 4 << MATF_FLAG_SHIFT // alpha blended
+ MAT_DEATH = 1 << MATF_FLAG_SHIFT, // force player suicide
+ MAT_ALPHA = 4 << MATF_FLAG_SHIFT // alpha blended
};
#define isliquid(mat) ((mat)==MAT_WATER || (mat)==MAT_LAVA)
@@ -45,7 +45,7 @@ extern entity *brightestlight(const vec &target, const vec &dir);
enum { RAY_BB = 1, RAY_POLY = 3, RAY_ALPHAPOLY = 7, RAY_ENTS = 9, RAY_CLIPMAT = 16, RAY_SKIPFIRST = 32, RAY_EDITMAT = 64, RAY_SHADOW = 128, RAY_PASS = 256, RAY_SKIPSKY = 512, RAY_SKYTEX = 1024 };
-extern float raycube (const vec &o, const vec &ray, float radius = 0, int mode = RAY_CLIPMAT, int size = 0, extentity *t = 0);
+extern float raycube (const vec &o, const vec &ray, float radius = 0, int mode = RAY_CLIPMAT, int size = 0, extentity *t = 0);
extern float raycubepos(const vec &o, const vec &ray, vec &hit, float radius = 0, int mode = RAY_CLIPMAT, int size = 0);
extern float rayfloor (const vec &o, vec &floor, int mode = 0, float radius = 0);
extern bool raycubelos(const vec &o, const vec &dest, vec &hitpos);
@@ -61,27 +61,27 @@ enum { EDIT_FACE = 0, EDIT_TEX, EDIT_MAT, EDIT_FLIP, EDIT_COPY, EDIT_PASTE, EDIT
struct selinfo
{
- int corner;
- int cx, cxs, cy, cys;
- ivec o, s;
- int grid, orient;
- selinfo() : corner(0), cx(0), cxs(0), cy(0), cys(0), o(0, 0, 0), s(0, 0, 0), grid(8), orient(0) {}
- int size() const { return s.x*s.y*s.z; }
- int us(int d) const { return s[d]*grid; }
- bool operator==(const selinfo &sel) const { return o==sel.o && s==sel.s && grid==sel.grid && orient==sel.orient; }
- bool validate()
- {
- extern int worldsize;
- if(grid <= 0 || grid >= worldsize) return false;
- if(o.x >= worldsize || o.y >= worldsize || o.z >= worldsize) return false;
- if(o.x < 0) { s.x -= (grid - 1 - o.x)/grid; o.x = 0; }
- if(o.y < 0) { s.y -= (grid - 1 - o.y)/grid; o.y = 0; }
- if(o.z < 0) { s.z -= (grid - 1 - o.z)/grid; o.z = 0; }
- s.x = clamp(s.x, 0, (worldsize - o.x)/grid);
- s.y = clamp(s.y, 0, (worldsize - o.y)/grid);
- s.z = clamp(s.z, 0, (worldsize - o.z)/grid);
- return s.x > 0 && s.y > 0 && s.z > 0;
- }
+ int corner;
+ int cx, cxs, cy, cys;
+ ivec o, s;
+ int grid, orient;
+ selinfo() : corner(0), cx(0), cxs(0), cy(0), cys(0), o(0, 0, 0), s(0, 0, 0), grid(8), orient(0) {}
+ int size() const { return s.x*s.y*s.z; }
+ int us(int d) const { return s[d]*grid; }
+ bool operator==(const selinfo &sel) const { return o==sel.o && s==sel.s && grid==sel.grid && orient==sel.orient; }
+ bool validate()
+ {
+ extern int worldsize;
+ if(grid <= 0 || grid >= worldsize) return false;
+ if(o.x >= worldsize || o.y >= worldsize || o.z >= worldsize) return false;
+ if(o.x < 0) { s.x -= (grid - 1 - o.x)/grid; o.x = 0; }
+ if(o.y < 0) { s.y -= (grid - 1 - o.y)/grid; o.y = 0; }
+ if(o.z < 0) { s.z -= (grid - 1 - o.z)/grid; o.z = 0; }
+ s.x = clamp(s.x, 0, (worldsize - o.x)/grid);
+ s.y = clamp(s.y, 0, (worldsize - o.y)/grid);
+ s.z = clamp(s.z, 0, (worldsize - o.z)/grid);
+ return s.x > 0 && s.y > 0 && s.z > 0;
+ }
};
struct editinfo;
@@ -187,16 +187,16 @@ static inline void loopiter(ident *id, identstack &stack, const char *s) { tagva
enum
{
- CON_INFO = 1<<0,
- CON_WARN = 1<<1,
- CON_ERROR = 1<<2,
- CON_DEBUG = 1<<3,
- CON_INIT = 1<<4,
- CON_ECHO = 1<<5,
-
- CON_FLAGS = 0xFFFF,
- CON_TAG_SHIFT = 16,
- CON_TAG_MASK = (0x7FFF << CON_TAG_SHIFT)
+ CON_INFO = 1<<0,
+ CON_WARN = 1<<1,
+ CON_ERROR = 1<<2,
+ CON_DEBUG = 1<<3,
+ CON_INIT = 1<<4,
+ CON_ECHO = 1<<5,
+
+ CON_FLAGS = 0xFFFF,
+ CON_TAG_SHIFT = 16,
+ CON_TAG_MASK = (0x7FFF << CON_TAG_SHIFT)
};
extern void conoutf(const char *s, ...) PRINTFARGS(1, 2);
@@ -221,14 +221,14 @@ extern int lookupmaterial(const vec &o);
static inline bool insideworld(const vec &o)
{
- extern int worldsize;
- return o.x>=0 && o.x<worldsize && o.y>=0 && o.y<worldsize && o.z>=0 && o.z<worldsize;
+ extern int worldsize;
+ return o.x>=0 && o.x<worldsize && o.y>=0 && o.y<worldsize && o.z>=0 && o.z<worldsize;
}
static inline bool insideworld(const ivec &o)
{
- extern int worldsize;
- return uint(o.x)<uint(worldsize) && uint(o.y)<uint(worldsize) && uint(o.z)<uint(worldsize);
+ extern int worldsize;
+ return uint(o.x)<uint(worldsize) && uint(o.y)<uint(worldsize) && uint(o.z)<uint(worldsize);
}
// world
@@ -263,31 +263,31 @@ extern void text_posf(const char *str, int cursor, float &cx, float &cy, int max
static inline int text_width(const char *str)
{
- return int(ceil(text_widthf(str)));
+ return int(ceil(text_widthf(str)));
}
static inline void text_bounds(const char *str, int &width, int &height, int maxwidth = -1)
{
- float widthf, heightf;
- text_boundsf(str, widthf, heightf, maxwidth);
- width = int(ceil(widthf));
- height = int(ceil(heightf));
+ float widthf, heightf;
+ text_boundsf(str, widthf, heightf, maxwidth);
+ width = int(ceil(widthf));
+ height = int(ceil(heightf));
}
static inline void text_pos(const char *str, int cursor, int &cx, int &cy, int maxwidth)
{
- float cxf, cyf;
- text_posf(str, cursor, cxf, cyf, maxwidth);
- cx = int(cxf);
- cy = int(cyf);
+ float cxf, cyf;
+ text_posf(str, cursor, cxf, cyf, maxwidth);
+ cx = int(cxf);
+ cy = int(cyf);
}
// renderva
enum
{
- DL_SHRINK = 1<<0,
- DL_EXPAND = 1<<1,
- DL_FLASH = 1<<2
+ DL_SHRINK = 1<<0,
+ DL_EXPAND = 1<<1,
+ DL_FLASH = 1<<2
};
extern void adddynlight(const vec &o, float radius, const vec &color, int fade = 0, int peak = 0, int flags = 0, float initradius = 0, const vec &initcolor = vec(0, 0, 0), physent *owner = NULL);
@@ -303,9 +303,7 @@ extern void disablezoom();
extern vec calcavatarpos(const vec &pos, float dist);
extern vec calcmodelpreviewpos(const vec &radius, float &yaw);
-extern void damageblend(int n);
extern void damagecompass(int n, const vec &loc);
-extern void cleardamagescreen();
extern matrix4 hudmatrix;
extern void resethudmatrix();
@@ -318,23 +316,23 @@ extern void pushhudtranslate(float tx, float ty, float sx = 0, float sy = 0);
// renderparticles
enum
{
- PART_BLOOD = 0,
- PART_WATER,
- PART_SMOKE,
- PART_STEAM,
- PART_FLAME,
- PART_FIREBALL1, PART_FIREBALL2, PART_FIREBALL3,
- PART_STREAK, PART_LIGHTNING,
- PART_EXPLOSION, PART_EXPLOSION_BLUE,
- PART_SPARK, PART_EDIT,
- PART_SNOW,
- PART_MUZZLE_FLASH1, PART_MUZZLE_FLASH2, PART_MUZZLE_FLASH3,
- PART_HUD_ICON,
- PART_HUD_ICON_GREY,
- PART_TEXT,
- PART_TEXT_ICON,
- PART_METER, PART_METER_VS,
- PART_LENS_FLARE
+ PART_BLOOD = 0,
+ PART_WATER,
+ PART_SMOKE,
+ PART_STEAM,
+ PART_FLAME,
+ PART_FIREBALL1, PART_FIREBALL2, PART_FIREBALL3,
+ PART_STREAK, PART_LIGHTNING,
+ PART_EXPLOSION, PART_EXPLOSION_BLUE,
+ PART_SPARK, PART_EDIT,
+ PART_SNOW,
+ PART_MUZZLE_FLASH1, PART_MUZZLE_FLASH2, PART_MUZZLE_FLASH3,
+ PART_HUD_ICON,
+ PART_HUD_ICON_GREY,
+ PART_TEXT,
+ PART_TEXT_ICON,
+ PART_METER, PART_METER_VS,
+ PART_LENS_FLARE
};
extern bool canaddparticles();
@@ -354,9 +352,9 @@ extern void removetrackedparticles(physent *owner = NULL);
// decal
enum
{
- DECAL_SCORCH = 0,
- DECAL_BLOOD,
- DECAL_BULLET
+ DECAL_SCORCH = 0,
+ DECAL_BLOOD,
+ DECAL_BULLET
};
extern void adddecal(int type, const vec &center, const vec &surface, float radius, const bvec &color = bvec(0xFF, 0xFF, 0xFF), int info = 0);
@@ -385,11 +383,9 @@ extern bool overlapsdynent(const vec &o, float radius);
extern bool movecamera(physent *pl, const vec &dir, float dist, float stepdist);
extern void physicsframe();
extern void dropenttofloor(entity *e);
-extern bool droptofloor(vec &o, float radius, float height);
extern void vecfromyawpitch(float yaw, float pitch, int move, int strafe, vec &m);
extern void vectoyawpitch(const vec &v, float &yaw, float &pitch);
-extern bool moveplatform(physent *p, const vec &dir);
extern void updatephysstate(physent *d);
extern void cleardynentcache();
extern void updatedynentcache(physent *d);
@@ -399,9 +395,9 @@ extern void findplayerspawn(dynent *d, int forceent = -1, int tag = 0);
// sound
enum
{
- SND_MAP = 1<<0,
- SND_NO_ALT = 1<<1,
- SND_USE_ALT = 1<<2
+ SND_MAP = 1<<0,
+ SND_NO_ALT = 1<<1,
+ SND_USE_ALT = 1<<2
};
extern int playsound(int n, const vec *loc = NULL, extentity *ent = NULL, int flags = 0, int loops = 0, int fade = 0, int chanid = -1, int radius = 0, int expire = -1);
@@ -418,14 +414,14 @@ enum { MDL_CULL_VFC = 1<<0, MDL_CULL_DIST = 1<<1, MDL_CULL_OCCLUDED = 1<<2, MDL_
struct model;
struct modelattach
{
- const char *tag, *name;
- int anim, basetime;
- vec *pos;
- model *m;
-
- modelattach() : tag(NULL), name(NULL), anim(-1), basetime(0), pos(NULL), m(NULL) {}
- modelattach(const char *tag, const char *name, int anim = -1, int basetime = 0) : tag(tag), name(name), anim(anim), basetime(basetime), pos(NULL), m(NULL) {}
- modelattach(const char *tag, vec *pos) : tag(tag), name(NULL), anim(-1), basetime(0), pos(pos), m(NULL) {}
+ const char *tag, *name;
+ int anim, basetime;
+ vec *pos;
+ model *m;
+
+ modelattach() : tag(NULL), name(NULL), anim(-1), basetime(0), pos(NULL), m(NULL) {}
+ modelattach(const char *tag, const char *name, int anim = -1, int basetime = 0) : tag(tag), name(name), anim(anim), basetime(basetime), pos(NULL), m(NULL) {}
+ modelattach(const char *tag, vec *pos) : tag(tag), name(NULL), anim(-1), basetime(0), pos(pos), m(NULL) {}
};
extern void startmodelbatches();
@@ -447,8 +443,8 @@ extern void moveragdoll(dynent *d);
extern void cleanragdoll(dynent *d);
// server
-#define MAXCLIENTS 128 // DO NOT set this any higher
-#define MAXTRANS 5000 // max amount of data to swallow in 1 go
+#define MAXCLIENTS 128 // DO NOT set this any higher
+#define MAXTRANS 5000 // max amount of data to swallow in 1 go
extern int maxclients;
@@ -506,70 +502,70 @@ enum { EDITORFOCUSED = 1, EDITORUSED, EDITORFOREVER };
struct g3d_gui
{
- virtual ~g3d_gui() {}
-
- virtual void start(int starttime, float basescale, int *tab = NULL, bool allowinput = true) = 0;
- virtual void end() = 0;
-
- virtual int text(const char *text, int color, const char *icon = NULL) = 0;
- int textf(const char *fmt, int color, const char *icon = NULL, ...) PRINTFARGS(2, 5)
- {
- defvformatstring(str, icon, fmt);
- return text(str, color, icon);
- }
- virtual int button(const char *text, int color, const char *icon = NULL) = 0;
- int buttonf(const char *fmt, int color, const char *icon = NULL, ...) PRINTFARGS(2, 5)
- {
- defvformatstring(str, icon, fmt);
- return button(str, color, icon);
- }
- virtual int title(const char *text, int color, const char *icon = NULL) = 0;
- int titlef(const char *fmt, int color, const char *icon = NULL, ...) PRINTFARGS(2, 5)
- {
- defvformatstring(str, icon, fmt);
- return title(str, color, icon);
- }
- virtual void background(int color, int parentw = 0, int parenth = 0) = 0;
-
- virtual void pushlist() {}
- virtual void poplist() {}
-
- virtual bool allowautotab(bool on) = 0;
- virtual bool shouldtab() = 0;
- virtual void tab(const char *name = NULL, int color = 0) = 0;
- virtual int image(Texture *t, float scale, const char *overlaid = NULL) = 0;
- virtual int texture(VSlot &vslot, float scale, bool overlaid = true) = 0;
- virtual int playerpreview(int model, int team, int weap, float scale, const char *overlaid = NULL) = 0;
- virtual int modelpreview(const char *name, int anim, float scale, const char *overlaid = NULL, bool throttle = false) = 0;
- virtual int prefabpreview(const char *prefab, const vec &color, float scale, const char *overlaid = NULL, bool throttle = false) = 0;
- virtual void slider(int &val, int vmin, int vmax, int color, const char *label = NULL) = 0;
- virtual void separator() = 0;
- virtual void progress(float percent) = 0;
- virtual void strut(float size) = 0;
- virtual void space(float size) = 0;
- virtual void spring(int weight = 1) = 0;
- virtual void column(int col) = 0;
- virtual char *keyfield(const char *name, int color, int length, int height = 0, const char *initval = NULL, int initmode = EDITORFOCUSED) = 0;
- virtual char *field(const char *name, int color, int length, int height = 0, const char *initval = NULL, int initmode = EDITORFOCUSED) = 0;
- virtual void textbox(const char *text, int width, int height, int color = 0xFFFFFF) = 0;
- virtual bool mergehits(bool on) = 0;
+ virtual ~g3d_gui() {}
+
+ virtual void start(int starttime, float basescale, int *tab = NULL, bool allowinput = true) = 0;
+ virtual void end() = 0;
+
+ virtual int text(const char *text, int color, const char *icon = NULL) = 0;
+ int textf(const char *fmt, int color, const char *icon = NULL, ...) PRINTFARGS(2, 5)
+ {
+ defvformatstring(str, icon, fmt);
+ return text(str, color, icon);
+ }
+ virtual int button(const char *text, int color, const char *icon = NULL) = 0;
+ int buttonf(const char *fmt, int color, const char *icon = NULL, ...) PRINTFARGS(2, 5)
+ {
+ defvformatstring(str, icon, fmt);
+ return button(str, color, icon);
+ }
+ virtual int title(const char *text, int color, const char *icon = NULL) = 0;
+ int titlef(const char *fmt, int color, const char *icon = NULL, ...) PRINTFARGS(2, 5)
+ {
+ defvformatstring(str, icon, fmt);
+ return title(str, color, icon);
+ }
+ virtual void background(int color, int parentw = 0, int parenth = 0) = 0;
+
+ virtual void pushlist() {}
+ virtual void poplist() {}
+
+ virtual bool allowautotab(bool on) = 0;
+ virtual bool shouldtab() = 0;
+ virtual void tab(const char *name = NULL, int color = 0) = 0;
+ virtual int image(Texture *t, float scale, const char *overlaid = NULL) = 0;
+ virtual int texture(VSlot &vslot, float scale, bool overlaid = true) = 0;
+ virtual int playerpreview(int model, int team, int weap, float scale, const char *overlaid = NULL) = 0;
+ virtual int modelpreview(const char *name, int anim, float scale, const char *overlaid = NULL, bool throttle = false) = 0;
+ virtual int prefabpreview(const char *prefab, const vec &color, float scale, const char *overlaid = NULL, bool throttle = false) = 0;
+ virtual void slider(int &val, int vmin, int vmax, int color, const char *label = NULL) = 0;
+ virtual void separator() = 0;
+ virtual void progress(float percent) = 0;
+ virtual void strut(float size) = 0;
+ virtual void space(float size) = 0;
+ virtual void spring(int weight = 1) = 0;
+ virtual void column(int col) = 0;
+ virtual char *keyfield(const char *name, int color, int length, int height = 0, const char *initval = NULL, int initmode = EDITORFOCUSED) = 0;
+ virtual char *field(const char *name, int color, int length, int height = 0, const char *initval = NULL, int initmode = EDITORFOCUSED) = 0;
+ virtual void textbox(const char *text, int width, int height, int color = 0xFFFFFF) = 0;
+ virtual bool mergehits(bool on) = 0;
};
struct g3d_callback
{
- virtual ~g3d_callback() {}
+ virtual ~g3d_callback() {}
- int starttime() { return totalmillis; }
+ int starttime() { return totalmillis; }
- virtual void gui(g3d_gui &g, bool firstpass) = 0;
+ virtual void gui(g3d_gui &g, bool firstpass) = 0;
};
enum
{
- GUI_2D = 1<<0,
- GUI_FOLLOW = 1<<1,
- GUI_FORCE_2D = 1<<2,
- GUI_BOTTOM = 1<<3
+ GUI_2D = 1<<0,
+ GUI_FOLLOW = 1<<1,
+ GUI_FORCE_2D = 1<<2,
+ GUI_BOTTOM = 1<<3
};
extern void g3d_addgui(g3d_callback *cb, vec &origin, int flags = 0);
diff --git a/src/shared/igame.h b/src/shared/igame.h
index dee14cb..1e7821a 100644
--- a/src/shared/igame.h
+++ b/src/shared/igame.h
@@ -2,125 +2,125 @@
namespace entities
{
- extern void editent(int i, bool local);
- extern const char *entnameinfo(entity &e);
- extern const char *entname(int i);
- extern int extraentinfosize();
- extern void writeent(entity &e, char *buf);
- extern void readent(entity &e, char *buf, int ver);
- extern void fixentity(extentity &e);
- extern void entradius(extentity &e, bool color);
- extern bool mayattach(extentity &e);
- extern bool attachent(extentity &e, extentity &a);
- extern bool printent(extentity &e, char *buf, int len);
- extern extentity *newentity();
- extern void deleteentity(extentity *e);
- extern void clearents();
- extern vector<extentity *> &getents();
- extern const char *entmodel(const entity &e);
+ extern void editent(int i, bool local);
+ extern const char *entnameinfo(entity &e);
+ extern const char *entname(int i);
+ extern int extraentinfosize();
+ extern void writeent(entity &e, char *buf);
+ extern void readent(entity &e, char *buf, int ver);
+ extern void fixentity(extentity &e);
+ extern void entradius(extentity &e, bool color);
+ extern bool mayattach(extentity &e);
+ extern bool attachent(extentity &e, extentity &a);
+ extern bool printent(extentity &e, char *buf, int len);
+ extern extentity *newentity();
+ extern void deleteentity(extentity *e);
+ extern void clearents();
+ extern vector<extentity *> &getents();
+ extern const char *entmodel(const entity &e);
}
namespace game
{
- extern void parseoptions(vector<const char *> &args);
+ extern void parseoptions(vector<const char *> &args);
- extern void gamedisconnect(bool cleanup);
- extern void parsepacketclient(int chan, packetbuf &p);
- extern void connectattempt(const char *name, const char *password, const ENetAddress &address);
- extern void connectfail();
- extern void gameconnect(bool _remote);
- extern bool allowedittoggle();
- extern void edittoggled(bool on);
- extern void writeclientinfo(stream *f);
- extern void toserver(char *text);
- extern void changemap(const char *name);
- extern void forceedit(const char *name);
- extern bool ispaused();
- extern int scaletime(int t);
- extern bool allowmouselook();
+ extern void gamedisconnect(bool cleanup);
+ extern void parsepacketclient(int chan, packetbuf &p);
+ extern void connectattempt(const char *name, const char *password, const ENetAddress &address);
+ extern void connectfail();
+ extern void gameconnect(bool _remote);
+ extern bool allowedittoggle();
+ extern void edittoggled(bool on);
+ extern void writeclientinfo(stream *f);
+ extern void toserver(char *text);
+ extern void changemap(const char *name);
+ extern void forceedit(const char *name);
+ extern bool ispaused();
+ extern int scaletime(int t);
+ extern bool allowmouselook();
- extern const char *gameident();
- extern const char *savedconfig();
- extern const char *restoreconfig();
- extern const char *defaultconfig();
- extern const char *autoexec();
- extern const char *savedservers();
- extern void loadconfigs();
+ extern const char *gameident();
+ extern const char *savedconfig();
+ extern const char *restoreconfig();
+ extern const char *defaultconfig();
+ extern const char *autoexec();
+ extern const char *savedservers();
+ extern void loadconfigs();
- extern void updateworld();
- extern void initclient();
- extern void physicstrigger(physent *d, bool local, int floorlevel, int waterlevel, int material = 0);
- extern void bounced(physent *d, const vec &surface);
- extern void edittrigger(const selinfo &sel, int op, int arg1 = 0, int arg2 = 0, int arg3 = 0, const VSlot *vs = NULL);
- extern void vartrigger(ident *id);
- extern void dynentcollide(physent *d, physent *o, const vec &dir);
- extern const char *getclientmap();
- extern const char *getmapinfo();
- extern const char *getscreenshotinfo();
- extern void resetgamestate();
- extern void suicide(physent *d);
- extern float ratespawn(dynent *d, const extentity &e);
- extern void newmap(int size);
- extern void loadingmap(const char *name);
- extern void startmap(const char *name);
- extern void preload();
- extern float abovegameplayhud(int w, int h);
- extern void gameplayhud(int w, int h);
- extern bool canjump();
- extern bool allowmove(physent *d);
- extern void doattack(bool on);
- extern dynent *iterdynents(int i);
- extern int numdynents();
- extern void rendergame(bool mainpass);
- extern void renderavatar();
- extern void renderplayerpreview(int model, int team, int weap);
- extern void writegamedata(vector<char> &extras);
- extern void readgamedata(vector<char> &extras);
- extern int clipconsole(int w, int h);
- extern void g3d_gamemenus();
- extern const char *defaultcrosshair(int index);
- extern int selectcrosshair(vec &color);
- extern void lighteffects(dynent *d, vec &color, vec &dir);
- extern void setupcamera();
- extern bool allowthirdperson(bool msg = false);
- extern bool detachcamera();
- extern bool collidecamera();
- extern void adddynlights();
- extern void particletrack(physent *owner, vec &o, vec &d);
- extern void dynlighttrack(physent *owner, vec &o, vec &hud);
- extern int maxsoundradius(int n);
- extern bool serverinfostartcolumn(g3d_gui *g, int i);
- extern void serverinfoendcolumn(g3d_gui *g, int i);
- extern bool serverinfoentry(g3d_gui *g, int i, const char *name, int port, const char *desc, const char *map, int ping, const vector<int> &attr, int np);
+ extern void updateworld();
+ extern void initclient();
+ extern void physicstrigger(physent *d, bool local, int floorlevel, int waterlevel, int material = 0);
+ extern void bounced(physent *d, const vec &surface);
+ extern void edittrigger(const selinfo &sel, int op, int arg1 = 0, int arg2 = 0, int arg3 = 0, const VSlot *vs = NULL);
+ extern void vartrigger(ident *id);
+ extern void dynentcollide(physent *d, physent *o, const vec &dir);
+ extern const char *getclientmap();
+ extern const char *getmapinfo();
+ extern const char *getscreenshotinfo();
+ extern void resetgamestate();
+ extern void suicide(physent *d);
+ extern float ratespawn(dynent *d, const extentity &e);
+ extern void newmap(int size);
+ extern void loadingmap(const char *name);
+ extern void startmap(const char *name);
+ extern void preload();
+ extern float abovegameplayhud(int w, int h);
+ extern void gameplayhud(int w, int h);
+ extern bool canjump();
+ extern bool allowmove(physent *d);
+ extern void doattack(bool on);
+ extern dynent *iterdynents(int i);
+ extern int numdynents();
+ extern void rendergame(bool mainpass);
+ extern void renderavatar();
+ extern void renderplayerpreview(int model, int team, int weap);
+ extern void writegamedata(vector<char> &extras);
+ extern void readgamedata(vector<char> &extras);
+ extern int clipconsole(int w, int h);
+ extern void g3d_gamemenus();
+ extern const char *defaultcrosshair(int index);
+ extern int selectcrosshair(vec &color);
+ extern void lighteffects(dynent *d, vec &color, vec &dir);
+ extern void setupcamera();
+ extern bool allowthirdperson(bool msg = false);
+ extern bool detachcamera();
+ extern bool collidecamera();
+ extern void adddynlights();
+ extern void particletrack(physent *owner, vec &o, vec &d);
+ extern void dynlighttrack(physent *owner, vec &o, vec &hud);
+ extern int maxsoundradius(int n);
+ extern bool serverinfostartcolumn(g3d_gui *g, int i);
+ extern void serverinfoendcolumn(g3d_gui *g, int i);
+ extern bool serverinfoentry(g3d_gui *g, int i, const char *name, int port, const char *desc, const char *map, int ping, const vector<int> &attr, int np);
}
namespace server
{
- extern void *newclientinfo();
- extern void deleteclientinfo(void *ci);
- extern void serverinit();
- extern int reserveclients();
- extern int numchannels();
- extern void clientdisconnect(int n);
- extern int clientconnect(int n);
- extern void localdisconnect(int n);
- extern void localconnect(int n);
- extern bool allowbroadcast(int n);
- extern void recordpacket(int chan, void *data, int len);
- extern void parsepacket(int sender, int chan, packetbuf &p);
- extern void sendservmsg(const char *s);
- extern bool sendpackets(bool force = false);
- extern void serverinforeply(ucharbuf &req, ucharbuf &p);
- extern void serverupdate();
- extern int laninfoport();
- extern int serverinfoport(int servport = -1);
- extern int serverport(int infoport = -1);
- extern const char *defaultmaster();
- extern int masterport();
- extern void processmasterinput(const char *cmd, int cmdlen, const char *args);
- extern void masterconnected();
- extern void masterdisconnected();
- extern bool ispaused();
- extern int scaletime(int t);
+ extern void *newclientinfo();
+ extern void deleteclientinfo(void *ci);
+ extern void serverinit();
+ extern int reserveclients();
+ extern int numchannels();
+ extern void clientdisconnect(int n);
+ extern int clientconnect(int n);
+ extern void localdisconnect(int n);
+ extern void localconnect(int n);
+ extern bool allowbroadcast(int n);
+ extern void recordpacket(int chan, void *data, int len);
+ extern void parsepacket(int sender, int chan, packetbuf &p);
+ extern void sendservmsg(const char *s);
+ extern bool sendpackets(bool force = false);
+ extern void serverinforeply(ucharbuf &req, ucharbuf &p);
+ extern void serverupdate();
+ extern int laninfoport();
+ extern int serverinfoport(int servport = -1);
+ extern int serverport(int infoport = -1);
+ extern const char *defaultmaster();
+ extern int masterport();
+ extern void processmasterinput(const char *cmd, int cmdlen, const char *args);
+ extern void masterconnected();
+ extern void masterdisconnected();
+ extern bool ispaused();
+ extern int scaletime(int t);
}
diff --git a/src/shared/stream.cpp b/src/shared/stream.cpp
index 888caa8..8f218ad 100644
--- a/src/shared/stream.cpp
+++ b/src/shared/stream.cpp
@@ -4,1215 +4,1173 @@
void conoutf(const char *fmt, ...)
{
- va_list args;
- va_start(args, fmt);
- conoutfv(CON_INFO, fmt, args);
- va_end(args);
+ va_list args;
+ va_start(args, fmt);
+ conoutfv(CON_INFO, fmt, args);
+ va_end(args);
}
void conoutf(int type, const char *fmt, ...)
{
- va_list args;
- va_start(args, fmt);
- conoutfv(type, fmt, args);
- va_end(args);
+ va_list args;
+ va_start(args, fmt);
+ conoutfv(type, fmt, args);
+ va_end(args);
}
void conoutf(int type, int tag, const char *fmt, ...)
{
- va_list args;
- va_start(args, fmt);
- conoutfv(type | ((tag << CON_TAG_SHIFT) & CON_TAG_MASK), fmt, args);
- va_end(args);
+ va_list args;
+ va_start(args, fmt);
+ conoutfv(type | ((tag << CON_TAG_SHIFT) & CON_TAG_MASK), fmt, args);
+ va_end(args);
}
///////////////////////// character conversion ///////////////
#define CUBECTYPE(s, p, d, a, A, u, U) \
- 0, U, U, U, U, U, U, U, U, s, s, s, s, s, U, U, \
- U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, \
- s, p, p, p, p, p, p, p, p, p, p, p, p, p, p, p, \
- d, d, d, d, d, d, d, d, d, d, p, p, p, p, p, p, \
- p, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, \
- A, A, A, A, A, A, A, A, A, A, A, p, p, p, p, p, \
- p, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, \
- a, a, a, a, a, a, a, a, a, a, a, p, p, p, p, U, \
- U, u, u, u, u, u, u, u, u, u, u, u, u, u, u, u, \
- u, u, u, u, u, u, u, u, u, u, u, u, u, u, u, U, \
- u, U, u, U, u, U, u, U, u, U, u, U, u, U, u, U, \
- u, U, u, U, u, U, u, U, u, U, u, U, u, U, u, U, \
- u, U, u, U, u, U, u, U, U, u, U, u, U, u, U, U, \
- U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, \
- U, U, U, U, u, u, u, u, u, u, u, u, u, u, u, u, \
- u, u, u, u, u, u, u, u, u, u, u, u, u, u, U, u
+ 0, U, U, U, U, U, U, U, U, s, s, s, s, s, U, U, \
+ U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, \
+ s, p, p, p, p, p, p, p, p, p, p, p, p, p, p, p, \
+ d, d, d, d, d, d, d, d, d, d, p, p, p, p, p, p, \
+ p, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, \
+ A, A, A, A, A, A, A, A, A, A, A, p, p, p, p, p, \
+ p, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, \
+ a, a, a, a, a, a, a, a, a, a, a, p, p, p, p, U, \
+ U, u, u, u, u, u, u, u, u, u, u, u, u, u, u, u, \
+ u, u, u, u, u, u, u, u, u, u, u, u, u, u, u, U, \
+ u, U, u, U, u, U, u, U, u, U, u, U, u, U, u, U, \
+ u, U, u, U, u, U, u, U, u, U, u, U, u, U, u, U, \
+ u, U, u, U, u, U, u, U, U, u, U, u, U, u, U, U, \
+ U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, \
+ U, U, U, U, u, u, u, u, u, u, u, u, u, u, u, u, \
+ u, u, u, u, u, u, u, u, u, u, u, u, u, u, U, u
extern const uchar cubectype[256] =
{
- CUBECTYPE(CT_SPACE,
- CT_PRINT,
- CT_PRINT|CT_DIGIT,
- CT_PRINT|CT_ALPHA|CT_LOWER,
- CT_PRINT|CT_ALPHA|CT_UPPER,
- CT_PRINT|CT_UNICODE|CT_ALPHA|CT_LOWER,
- CT_PRINT|CT_UNICODE|CT_ALPHA|CT_UPPER)
+ CUBECTYPE(CT_SPACE,
+ CT_PRINT,
+ CT_PRINT|CT_DIGIT,
+ CT_PRINT|CT_ALPHA|CT_LOWER,
+ CT_PRINT|CT_ALPHA|CT_UPPER,
+ CT_PRINT|CT_UNICODE|CT_ALPHA|CT_LOWER,
+ CT_PRINT|CT_UNICODE|CT_ALPHA|CT_UPPER)
};
extern const int cube2unichars[256] =
{
- 0, 192, 193, 194, 195, 196, 197, 198, 199, 9, 10, 11, 12, 13, 200, 201,
- 202, 203, 204, 205, 206, 207, 209, 210, 211, 212, 213, 214, 216, 217, 218, 219,
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
- 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
- 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
- 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
- 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 220,
- 221, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237,
- 238, 239, 241, 242, 243, 244, 245, 246, 248, 249, 250, 251, 252, 253, 255, 0x104,
- 0x105, 0x106, 0x107, 0x10C, 0x10D, 0x10E, 0x10F, 0x118, 0x119, 0x11A, 0x11B, 0x11E, 0x11F, 0x130, 0x131, 0x141,
- 0x142, 0x143, 0x144, 0x147, 0x148, 0x150, 0x151, 0x152, 0x153, 0x158, 0x159, 0x15A, 0x15B, 0x15E, 0x15F, 0x160,
- 0x161, 0x164, 0x165, 0x16E, 0x16F, 0x170, 0x171, 0x178, 0x179, 0x17A, 0x17B, 0x17C, 0x17D, 0x17E, 0x404, 0x411,
- 0x413, 0x414, 0x416, 0x417, 0x418, 0x419, 0x41B, 0x41F, 0x423, 0x424, 0x426, 0x427, 0x428, 0x429, 0x42A, 0x42B,
- 0x42C, 0x42D, 0x42E, 0x42F, 0x431, 0x432, 0x433, 0x434, 0x436, 0x437, 0x438, 0x439, 0x43A, 0x43B, 0x43C, 0x43D,
- 0x43F, 0x442, 0x444, 0x446, 0x447, 0x448, 0x449, 0x44A, 0x44B, 0x44C, 0x44D, 0x44E, 0x44F, 0x454, 0x490, 0x491
+ 0, 192, 193, 194, 195, 196, 197, 198, 199, 9, 10, 11, 12, 13, 200, 201,
+ 202, 203, 204, 205, 206, 207, 209, 210, 211, 212, 213, 214, 216, 217, 218, 219,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
+ 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 220,
+ 221, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237,
+ 238, 239, 241, 242, 243, 244, 245, 246, 248, 249, 250, 251, 252, 253, 255, 0x104,
+ 0x105, 0x106, 0x107, 0x10C, 0x10D, 0x10E, 0x10F, 0x118, 0x119, 0x11A, 0x11B, 0x11E, 0x11F, 0x130, 0x131, 0x141,
+ 0x142, 0x143, 0x144, 0x147, 0x148, 0x150, 0x151, 0x152, 0x153, 0x158, 0x159, 0x15A, 0x15B, 0x15E, 0x15F, 0x160,
+ 0x161, 0x164, 0x165, 0x16E, 0x16F, 0x170, 0x171, 0x178, 0x179, 0x17A, 0x17B, 0x17C, 0x17D, 0x17E, 0x404, 0x411,
+ 0x413, 0x414, 0x416, 0x417, 0x418, 0x419, 0x41B, 0x41F, 0x423, 0x424, 0x426, 0x427, 0x428, 0x429, 0x42A, 0x42B,
+ 0x42C, 0x42D, 0x42E, 0x42F, 0x431, 0x432, 0x433, 0x434, 0x436, 0x437, 0x438, 0x439, 0x43A, 0x43B, 0x43C, 0x43D,
+ 0x43F, 0x442, 0x444, 0x446, 0x447, 0x448, 0x449, 0x44A, 0x44B, 0x44C, 0x44D, 0x44E, 0x44F, 0x454, 0x490, 0x491
};
extern const int uni2cubeoffsets[8] =
{
- 0, 256, 658, 658, 512, 658, 658, 658
+ 0, 256, 658, 658, 512, 658, 658, 658
};
extern const uchar uni2cubechars[878] =
{
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 10, 11, 12, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
- 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
- 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1, 2, 3, 4, 5, 6, 7, 8, 14, 15, 16, 17, 18, 19, 20, 21, 0, 22, 23, 24, 25, 26, 27, 0, 28, 29, 30, 31, 127, 128, 0, 129,
- 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 0, 146, 147, 148, 149, 150, 151, 0, 152, 153, 154, 155, 156, 157, 0, 158,
- 0, 0, 0, 0, 159, 160, 161, 162, 0, 0, 0, 0, 163, 164, 165, 166, 0, 0, 0, 0, 0, 0, 0, 0, 167, 168, 169, 170, 0, 0, 171, 172,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 174, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 175, 176, 177, 178, 0, 0, 179, 180, 0, 0, 0, 0, 0, 0, 0, 181, 182, 183, 184, 0, 0, 0, 0, 185, 186, 187, 188, 0, 0, 189, 190,
- 191, 192, 0, 0, 193, 194, 0, 0, 0, 0, 0, 0, 0, 0, 195, 196, 197, 198, 0, 0, 0, 0, 0, 0, 199, 200, 201, 202, 203, 204, 205, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 17, 0, 0, 206, 83, 73, 21, 74, 0, 0, 0, 0, 0, 0, 0, 65, 207, 66, 208, 209, 69, 210, 211, 212, 213, 75, 214, 77, 72, 79, 215,
- 80, 67, 84, 216, 217, 88, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 97, 228, 229, 230, 231, 101, 232, 233, 234, 235, 236, 237, 238, 239, 111, 240,
- 112, 99, 241, 121, 242, 120, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 0, 141, 0, 0, 253, 115, 105, 145, 106, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 10, 11, 12, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 2, 3, 4, 5, 6, 7, 8, 14, 15, 16, 17, 18, 19, 20, 21, 0, 22, 23, 24, 25, 26, 27, 0, 28, 29, 30, 31, 127, 128, 0, 129,
+ 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 0, 146, 147, 148, 149, 150, 151, 0, 152, 153, 154, 155, 156, 157, 0, 158,
+ 0, 0, 0, 0, 159, 160, 161, 162, 0, 0, 0, 0, 163, 164, 165, 166, 0, 0, 0, 0, 0, 0, 0, 0, 167, 168, 169, 170, 0, 0, 171, 172,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 174, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 175, 176, 177, 178, 0, 0, 179, 180, 0, 0, 0, 0, 0, 0, 0, 181, 182, 183, 184, 0, 0, 0, 0, 185, 186, 187, 188, 0, 0, 189, 190,
+ 191, 192, 0, 0, 193, 194, 0, 0, 0, 0, 0, 0, 0, 0, 195, 196, 197, 198, 0, 0, 0, 0, 0, 0, 199, 200, 201, 202, 203, 204, 205, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 17, 0, 0, 206, 83, 73, 21, 74, 0, 0, 0, 0, 0, 0, 0, 65, 207, 66, 208, 209, 69, 210, 211, 212, 213, 75, 214, 77, 72, 79, 215,
+ 80, 67, 84, 216, 217, 88, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 97, 228, 229, 230, 231, 101, 232, 233, 234, 235, 236, 237, 238, 239, 111, 240,
+ 112, 99, 241, 121, 242, 120, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 0, 141, 0, 0, 253, 115, 105, 145, 106, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
extern const uchar cubelowerchars[256] =
{
- 0, 130, 131, 132, 133, 134, 135, 136, 137, 9, 10, 11, 12, 13, 138, 139,
- 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155,
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
- 64, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
- 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 91, 92, 93, 94, 95,
- 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
- 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 156,
- 157, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
- 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 160,
- 160, 162, 162, 164, 164, 166, 166, 168, 168, 170, 170, 172, 172, 105, 174, 176,
- 176, 178, 178, 180, 180, 182, 182, 184, 184, 186, 186, 188, 188, 190, 190, 192,
- 192, 194, 194, 196, 196, 198, 198, 158, 201, 201, 203, 203, 205, 205, 206, 207,
- 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
- 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
- 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
+ 0, 130, 131, 132, 133, 134, 135, 136, 137, 9, 10, 11, 12, 13, 138, 139,
+ 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
+ 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
+ 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 156,
+ 157, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
+ 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 160,
+ 160, 162, 162, 164, 164, 166, 166, 168, 168, 170, 170, 172, 172, 105, 174, 176,
+ 176, 178, 178, 180, 180, 182, 182, 184, 184, 186, 186, 188, 188, 190, 190, 192,
+ 192, 194, 194, 196, 196, 198, 198, 158, 201, 201, 203, 203, 205, 205, 206, 207,
+ 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
+ 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
+ 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
};
extern const uchar cubeupperchars[256] =
{
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
- 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
- 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
- 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
- 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123, 124, 125, 126, 127,
- 128, 129, 1, 2, 3, 4, 5, 6, 7, 8, 14, 15, 16, 17, 18, 19,
- 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 127, 128, 199, 159,
- 159, 161, 161, 163, 163, 165, 165, 167, 167, 169, 169, 171, 171, 173, 73, 175,
- 175, 177, 177, 179, 179, 181, 181, 183, 183, 185, 185, 187, 187, 189, 189, 191,
- 191, 193, 193, 195, 195, 197, 197, 199, 200, 200, 202, 202, 204, 204, 206, 207,
- 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
- 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
- 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123, 124, 125, 126, 127,
+ 128, 129, 1, 2, 3, 4, 5, 6, 7, 8, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 127, 128, 199, 159,
+ 159, 161, 161, 163, 163, 165, 165, 167, 167, 169, 169, 171, 171, 173, 73, 175,
+ 175, 177, 177, 179, 179, 181, 181, 183, 183, 185, 185, 187, 187, 189, 189, 191,
+ 191, 193, 193, 195, 195, 197, 197, 199, 200, 200, 202, 202, 204, 204, 206, 207,
+ 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
+ 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
+ 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
};
size_t decodeutf8(uchar *dstbuf, size_t dstlen, const uchar *srcbuf, size_t srclen, size_t *carry)
{
- uchar *dst = dstbuf, *dstend = &dstbuf[dstlen];
- const uchar *src = srcbuf, *srcend = &srcbuf[srclen];
- if(dstbuf == srcbuf)
- {
- int len = min(dstlen, srclen);
- for(const uchar *end4 = &srcbuf[len&~3]; src < end4; src += 4) if(*(const int *)src & 0x80808080) goto decode;
- for(const uchar *end = &srcbuf[len]; src < end; src++) if(*src & 0x80) goto decode;
- if(carry) *carry += len;
- return len;
- }
+ uchar *dst = dstbuf, *dstend = &dstbuf[dstlen];
+ const uchar *src = srcbuf, *srcend = &srcbuf[srclen];
+ if(dstbuf == srcbuf)
+ {
+ int len = min(dstlen, srclen);
+ for(const uchar *end4 = &srcbuf[len&~3]; src < end4; src += 4) if(*(const int *)src & 0x80808080) goto decode;
+ for(const uchar *end = &srcbuf[len]; src < end; src++) if(*src & 0x80) goto decode;
+ if(carry) *carry += len;
+ return len;
+ }
decode:
- dst += src - srcbuf;
- while(src < srcend && dst < dstend)
- {
- int c = *src++;
- if(c < 0x80) *dst++ = c;
- else if(c >= 0xC0)
- {
- int uni;
- if(c >= 0xE0)
- {
- if(c >= 0xF0)
- {
- if(c >= 0xF8)
- {
- if(c >= 0xFC)
- {
- if(c >= 0xFE) continue;
- uni = c&1; if(srcend - src < 5) break;
- c = *src; if((c&0xC0) != 0x80) continue; src++; uni = (uni<<6) | (c&0x3F);
- }
- else { uni = c&3; if(srcend - src < 4) break; }
- c = *src; if((c&0xC0) != 0x80) continue; src++; uni = (uni<<6) | (c&0x3F);
- }
- else { uni = c&7; if(srcend - src < 3) break; }
- c = *src; if((c&0xC0) != 0x80) continue; src++; uni = (uni<<6) | (c&0x3F);
- }
- else { uni = c&0xF; if(srcend - src < 2) break; }
- c = *src; if((c&0xC0) != 0x80) continue; src++; uni = (uni<<6) | (c&0x3F);
- }
- else { uni = c&0x1F; if(srcend - src < 1) break; }
- c = *src; if((c&0xC0) != 0x80) continue; src++; uni = (uni<<6) | (c&0x3F);
- c = uni2cube(uni);
- if(!c) continue;
- *dst++ = c;
- }
- }
- if(carry) *carry += src - srcbuf;
- return dst - dstbuf;
+ dst += src - srcbuf;
+ while(src < srcend && dst < dstend)
+ {
+ int c = *src++;
+ if(c < 0x80) *dst++ = c;
+ else if(c >= 0xC0)
+ {
+ int uni;
+ if(c >= 0xE0)
+ {
+ if(c >= 0xF0)
+ {
+ if(c >= 0xF8)
+ {
+ if(c >= 0xFC)
+ {
+ if(c >= 0xFE) continue;
+ uni = c&1; if(srcend - src < 5) break;
+ c = *src; if((c&0xC0) != 0x80) continue; src++; uni = (uni<<6) | (c&0x3F);
+ }
+ else { uni = c&3; if(srcend - src < 4) break; }
+ c = *src; if((c&0xC0) != 0x80) continue; src++; uni = (uni<<6) | (c&0x3F);
+ }
+ else { uni = c&7; if(srcend - src < 3) break; }
+ c = *src; if((c&0xC0) != 0x80) continue; src++; uni = (uni<<6) | (c&0x3F);
+ }
+ else { uni = c&0xF; if(srcend - src < 2) break; }
+ c = *src; if((c&0xC0) != 0x80) continue; src++; uni = (uni<<6) | (c&0x3F);
+ }
+ else { uni = c&0x1F; if(srcend - src < 1) break; }
+ c = *src; if((c&0xC0) != 0x80) continue; src++; uni = (uni<<6) | (c&0x3F);
+ c = uni2cube(uni);
+ if(!c) continue;
+ *dst++ = c;
+ }
+ }
+ if(carry) *carry += src - srcbuf;
+ return dst - dstbuf;
}
size_t encodeutf8(uchar *dstbuf, size_t dstlen, const uchar *srcbuf, size_t srclen, size_t *carry)
{
- uchar *dst = dstbuf, *dstend = &dstbuf[dstlen];
- const uchar *src = srcbuf, *srcend = &srcbuf[srclen];
- if(src < srcend && dst < dstend) do
- {
- int uni = cube2uni(*src);
- if(uni <= 0x7F)
- {
- if(dst >= dstend) goto done;
- const uchar *end = min(srcend, &src[dstend-dst]);
- do
- {
- if(uni == '\f')
- {
- if(++src >= srcend) goto done;
- goto uni1;
- }
- *dst++ = uni;
- if(++src >= end) goto done;
- uni = cube2uni(*src);
- }
- while(uni <= 0x7F);
- }
- if(uni <= 0x7FF) { if(dst + 2 > dstend) goto done; *dst++ = 0xC0 | (uni>>6); goto uni2; }
- else if(uni <= 0xFFFF) { if(dst + 3 > dstend) goto done; *dst++ = 0xE0 | (uni>>12); goto uni3; }
- else if(uni <= 0x1FFFFF) { if(dst + 4 > dstend) goto done; *dst++ = 0xF0 | (uni>>18); goto uni4; }
- else if(uni <= 0x3FFFFFF) { if(dst + 5 > dstend) goto done; *dst++ = 0xF8 | (uni>>24); goto uni5; }
- else if(uni <= 0x7FFFFFFF) { if(dst + 6 > dstend) goto done; *dst++ = 0xFC | (uni>>30); goto uni6; }
- else goto uni1;
- uni6: *dst++ = 0x80 | ((uni>>24)&0x3F);
- uni5: *dst++ = 0x80 | ((uni>>18)&0x3F);
- uni4: *dst++ = 0x80 | ((uni>>12)&0x3F);
- uni3: *dst++ = 0x80 | ((uni>>6)&0x3F);
- uni2: *dst++ = 0x80 | (uni&0x3F);
- uni1:;
- }
- while(++src < srcend);
+ uchar *dst = dstbuf, *dstend = &dstbuf[dstlen];
+ const uchar *src = srcbuf, *srcend = &srcbuf[srclen];
+ if(src < srcend && dst < dstend) do
+ {
+ int uni = cube2uni(*src);
+ if(uni <= 0x7F)
+ {
+ if(dst >= dstend) goto done;
+ const uchar *end = min(srcend, &src[dstend-dst]);
+ do
+ {
+ if(uni == '\f')
+ {
+ if(++src >= srcend) goto done;
+ goto uni1;
+ }
+ *dst++ = uni;
+ if(++src >= end) goto done;
+ uni = cube2uni(*src);
+ }
+ while(uni <= 0x7F);
+ }
+ if(uni <= 0x7FF) { if(dst + 2 > dstend) goto done; *dst++ = 0xC0 | (uni>>6); goto uni2; }
+ else if(uni <= 0xFFFF) { if(dst + 3 > dstend) goto done; *dst++ = 0xE0 | (uni>>12); goto uni3; }
+ else if(uni <= 0x1FFFFF) { if(dst + 4 > dstend) goto done; *dst++ = 0xF0 | (uni>>18); goto uni4; }
+ else if(uni <= 0x3FFFFFF) { if(dst + 5 > dstend) goto done; *dst++ = 0xF8 | (uni>>24); goto uni5; }
+ else if(uni <= 0x7FFFFFFF) { if(dst + 6 > dstend) goto done; *dst++ = 0xFC | (uni>>30); goto uni6; }
+ else goto uni1;
+ uni6: *dst++ = 0x80 | ((uni>>24)&0x3F);
+ uni5: *dst++ = 0x80 | ((uni>>18)&0x3F);
+ uni4: *dst++ = 0x80 | ((uni>>12)&0x3F);
+ uni3: *dst++ = 0x80 | ((uni>>6)&0x3F);
+ uni2: *dst++ = 0x80 | (uni&0x3F);
+ uni1:;
+ }
+ while(++src < srcend);
done:
- if(carry) *carry += src - srcbuf;
- return dst - dstbuf;
+ if(carry) *carry += src - srcbuf;
+ return dst - dstbuf;
}
///////////////////////// file system ///////////////////////
-#ifdef WIN32
-#include <shlobj.h>
-#else
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
-#endif
string homedir = "";
struct packagedir
{
- char *dir, *filter;
- size_t dirlen, filterlen;
+ char *dir, *filter;
+ size_t dirlen, filterlen;
};
vector<packagedir> packagedirs;
char *makerelpath(const char *dir, const char *file, const char *prefix, const char *cmd)
{
- static string tmp;
- if(prefix) copystring(tmp, prefix);
- else tmp[0] = '\0';
- if(file[0]=='<')
- {
- const char *end = strrchr(file, '>');
- if(end)
- {
- size_t len = strlen(tmp);
- copystring(&tmp[len], file, min(sizeof(tmp)-len, size_t(end+2-file)));
- file = end+1;
- }
- }
- if(cmd) concatstring(tmp, cmd);
- if(dir)
- {
- defformatstring(pname, "%s/%s", dir, file);
- concatstring(tmp, pname);
- }
- else concatstring(tmp, file);
- return tmp;
+ static string tmp;
+ if(prefix) copystring(tmp, prefix);
+ else tmp[0] = '\0';
+ if(file[0]=='<')
+ {
+ const char *end = strrchr(file, '>');
+ if(end)
+ {
+ size_t len = strlen(tmp);
+ copystring(&tmp[len], file, min(sizeof(tmp)-len, size_t(end+2-file)));
+ file = end+1;
+ }
+ }
+ if(cmd) concatstring(tmp, cmd);
+ if(dir)
+ {
+ defformatstring(pname, "%s/%s", dir, file);
+ concatstring(tmp, pname);
+ }
+ else concatstring(tmp, file);
+ return tmp;
}
char *path(char *s)
{
- for(char *curpart = s;;)
- {
- char *endpart = strchr(curpart, '&');
- if(endpart) *endpart = '\0';
- if(curpart[0]=='<')
- {
- char *file = strrchr(curpart, '>');
- if(!file) return s;
- curpart = file+1;
- }
- for(char *t = curpart; (t = strpbrk(t, "/\\")); *t++ = PATHDIV);
- for(char *prevdir = NULL, *curdir = curpart;;)
- {
- prevdir = curdir[0]==PATHDIV ? curdir+1 : curdir;
- curdir = strchr(prevdir, PATHDIV);
- if(!curdir) break;
- if(prevdir+1==curdir && prevdir[0]=='.')
- {
- memmove(prevdir, curdir+1, strlen(curdir+1)+1);
- curdir = prevdir;
- }
- else if(curdir[1]=='.' && curdir[2]=='.' && curdir[3]==PATHDIV)
- {
- if(prevdir+2==curdir && prevdir[0]=='.' && prevdir[1]=='.') continue;
- memmove(prevdir, curdir+4, strlen(curdir+4)+1);
- if(prevdir-2 >= curpart && prevdir[-1]==PATHDIV)
- {
- prevdir -= 2;
- while(prevdir-1 >= curpart && prevdir[-1] != PATHDIV) --prevdir;
- }
- curdir = prevdir;
- }
- }
- if(endpart)
- {
- *endpart = '&';
- curpart = endpart+1;
- }
- else break;
- }
- return s;
+ for(char *curpart = s;;)
+ {
+ char *endpart = strchr(curpart, '&');
+ if(endpart) *endpart = '\0';
+ if(curpart[0]=='<')
+ {
+ char *file = strrchr(curpart, '>');
+ if(!file) return s;
+ curpart = file+1;
+ }
+ for(char *t = curpart; (t = strpbrk(t, "/\\")); *t++ = PATHDIV);
+ for(char *prevdir = NULL, *curdir = curpart;;)
+ {
+ prevdir = curdir[0]==PATHDIV ? curdir+1 : curdir;
+ curdir = strchr(prevdir, PATHDIV);
+ if(!curdir) break;
+ if(prevdir+1==curdir && prevdir[0]=='.')
+ {
+ memmove(prevdir, curdir+1, strlen(curdir+1)+1);
+ curdir = prevdir;
+ }
+ else if(curdir[1]=='.' && curdir[2]=='.' && curdir[3]==PATHDIV)
+ {
+ if(prevdir+2==curdir && prevdir[0]=='.' && prevdir[1]=='.') continue;
+ memmove(prevdir, curdir+4, strlen(curdir+4)+1);
+ if(prevdir-2 >= curpart && prevdir[-1]==PATHDIV)
+ {
+ prevdir -= 2;
+ while(prevdir-1 >= curpart && prevdir[-1] != PATHDIV) --prevdir;
+ }
+ curdir = prevdir;
+ }
+ }
+ if(endpart)
+ {
+ *endpart = '&';
+ curpart = endpart+1;
+ }
+ else break;
+ }
+ return s;
}
char *path(const char *s, bool copy)
{
- static string tmp;
- copystring(tmp, s);
- path(tmp);
- return tmp;
+ static string tmp;
+ copystring(tmp, s);
+ path(tmp);
+ return tmp;
}
const char *parentdir(const char *directory)
{
- const char *p = directory + strlen(directory);
- while(p > directory && *p != '/' && *p != '\\') p--;
- static string parent;
- size_t len = p-directory+1;
- copystring(parent, directory, len);
- return parent;
+ const char *p = directory + strlen(directory);
+ while(p > directory && *p != '/' && *p != '\\') p--;
+ static string parent;
+ size_t len = p-directory+1;
+ copystring(parent, directory, len);
+ return parent;
}
bool fileexists(const char *path, const char *mode)
{
- bool exists = true;
- if(mode[0]=='w' || mode[0]=='a') path = parentdir(path);
-#ifdef WIN32
- if(GetFileAttributes(path[0] ? path : ".\\") == INVALID_FILE_ATTRIBUTES) exists = false;
-#else
- if(access(path[0] ? path : ".", mode[0]=='w' || mode[0]=='a' ? W_OK : (mode[0]=='d' ? X_OK : R_OK)) == -1) exists = false;
-#endif
- return exists;
+ bool exists = true;
+ if(mode[0]=='w' || mode[0]=='a') path = parentdir(path);
+ if(access(path[0] ? path : ".", mode[0]=='w' || mode[0]=='a' ? W_OK : (mode[0]=='d' ? X_OK : R_OK)) == -1) exists = false;
+ return exists;
}
bool createdir(const char *path)
{
- size_t len = strlen(path);
- if(path[len-1]==PATHDIV)
- {
- static string strip;
- path = copystring(strip, path, len);
- }
-#ifdef WIN32
- return CreateDirectory(path, NULL)!=0;
-#else
- return mkdir(path, 0777)==0;
-#endif
+ size_t len = strlen(path);
+ if(path[len-1]==PATHDIV)
+ {
+ static string strip;
+ path = copystring(strip, path, len);
+ }
+ return mkdir(path, 0777)==0;
}
size_t fixpackagedir(char *dir)
{
- path(dir);
- size_t len = strlen(dir);
- if(len > 0 && dir[len-1] != PATHDIV)
- {
- dir[len] = PATHDIV;
- dir[len+1] = '\0';
- }
- return len;
+ path(dir);
+ size_t len = strlen(dir);
+ if(len > 0 && dir[len-1] != PATHDIV)
+ {
+ dir[len] = PATHDIV;
+ dir[len+1] = '\0';
+ }
+ return len;
}
bool subhomedir(char *dst, int len, const char *src)
{
- const char *sub = strstr(src, "$HOME");
- if(!sub) sub = strchr(src, '~');
- if(sub && sub-src < len)
- {
-#ifdef WIN32
- char home[MAX_PATH+1];
- home[0] = '\0';
- if(SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, 0, home) != S_OK || !home[0]) return false;
-#else
- const char *home = getenv("HOME");
- if(!home || !home[0]) return false;
-#endif
- dst[sub-src] = '\0';
- concatstring(dst, home, len);
- concatstring(dst, sub+(*sub == '~' ? 1 : strlen("$HOME")), len);
- }
- return true;
+ const char *sub = strstr(src, "$HOME");
+ if(!sub) sub = strchr(src, '~');
+ if(sub && sub-src < len)
+ {
+ const char *home = getenv("HOME");
+ if(!home || !home[0]) return false;
+ dst[sub-src] = '\0';
+ concatstring(dst, home, len);
+ concatstring(dst, sub+(*sub == '~' ? 1 : strlen("$HOME")), len);
+ }
+ return true;
}
const char *sethomedir(const char *dir)
{
- string pdir;
- copystring(pdir, dir);
- if(!subhomedir(pdir, sizeof(pdir), dir) || !fixpackagedir(pdir)) return NULL;
- copystring(homedir, pdir);
- return homedir;
+ string pdir;
+ copystring(pdir, dir);
+ if(!subhomedir(pdir, sizeof(pdir), dir) || !fixpackagedir(pdir)) return NULL;
+ copystring(homedir, pdir);
+ return homedir;
}
const char *addpackagedir(const char *dir)
{
- string pdir;
- copystring(pdir, dir);
- if(!subhomedir(pdir, sizeof(pdir), dir) || !fixpackagedir(pdir)) return NULL;
- char *filter = pdir;
- for(;;)
- {
- static int len = strlen("packages");
- filter = strstr(filter, "packages");
- if(!filter) break;
- if(filter > pdir && filter[-1] == PATHDIV && filter[len] == PATHDIV) break;
- filter += len;
- }
- packagedir &pf = packagedirs.add();
- pf.dir = filter ? newstring(pdir, filter-pdir) : newstring(pdir);
- pf.dirlen = filter ? filter-pdir : strlen(pdir);
- pf.filter = filter ? newstring(filter) : NULL;
- pf.filterlen = filter ? strlen(filter) : 0;
- return pf.dir;
+ string pdir;
+ copystring(pdir, dir);
+ if(!subhomedir(pdir, sizeof(pdir), dir) || !fixpackagedir(pdir)) return NULL;
+ char *filter = pdir;
+ for(;;)
+ {
+ static int len = strlen("packages");
+ filter = strstr(filter, "packages");
+ if(!filter) break;
+ if(filter > pdir && filter[-1] == PATHDIV && filter[len] == PATHDIV) break;
+ filter += len;
+ }
+ packagedir &pf = packagedirs.add();
+ pf.dir = filter ? newstring(pdir, filter-pdir) : newstring(pdir);
+ pf.dirlen = filter ? filter-pdir : strlen(pdir);
+ pf.filter = filter ? newstring(filter) : NULL;
+ pf.filterlen = filter ? strlen(filter) : 0;
+ return pf.dir;
}
const char *findfile(const char *filename, const char *mode)
{
- static string s;
- if(homedir[0])
- {
- formatstring(s, "%s%s", homedir, filename);
- if(fileexists(s, mode)) return s;
- if(mode[0]=='w' || mode[0]=='a')
- {
- string dirs;
- copystring(dirs, s);
- char *dir = strchr(dirs[0]==PATHDIV ? dirs+1 : dirs, PATHDIV);
- while(dir)
- {
- *dir = '\0';
- if(!fileexists(dirs, "d") && !createdir(dirs)) return s;
- *dir = PATHDIV;
- dir = strchr(dir+1, PATHDIV);
- }
- return s;
- }
- }
- if(mode[0]=='w' || mode[0]=='a') return filename;
- loopv(packagedirs)
- {
- packagedir &pf = packagedirs[i];
- if(pf.filter && strncmp(filename, pf.filter, pf.filterlen)) continue;
- formatstring(s, "%s%s", pf.dir, filename);
- if(fileexists(s, mode)) return s;
- }
- if(mode[0]=='e') return NULL;
- return filename;
+ static string s;
+ if(homedir[0])
+ {
+ formatstring(s, "%s%s", homedir, filename);
+ if(fileexists(s, mode)) return s;
+ if(mode[0]=='w' || mode[0]=='a')
+ {
+ string dirs;
+ copystring(dirs, s);
+ char *dir = strchr(dirs[0]==PATHDIV ? dirs+1 : dirs, PATHDIV);
+ while(dir)
+ {
+ *dir = '\0';
+ if(!fileexists(dirs, "d") && !createdir(dirs)) return s;
+ *dir = PATHDIV;
+ dir = strchr(dir+1, PATHDIV);
+ }
+ return s;
+ }
+ }
+ if(mode[0]=='w' || mode[0]=='a') return filename;
+ loopv(packagedirs)
+ {
+ packagedir &pf = packagedirs[i];
+ if(pf.filter && strncmp(filename, pf.filter, pf.filterlen)) continue;
+ formatstring(s, "%s%s", pf.dir, filename);
+ if(fileexists(s, mode)) return s;
+ }
+ if(mode[0]=='e') return NULL;
+ return filename;
}
bool listdir(const char *dirname, bool rel, const char *ext, vector<char *> &files)
{
- size_t extsize = ext ? strlen(ext)+1 : 0;
-#ifdef WIN32
- defformatstring(pathname, rel ? ".\\%s\\*.%s" : "%s\\*.%s", dirname, ext ? ext : "*");
- WIN32_FIND_DATA FindFileData;
- HANDLE Find = FindFirstFile(pathname, &FindFileData);
- if(Find != INVALID_HANDLE_VALUE)
- {
- do {
- if(!ext) files.add(newstring(FindFileData.cFileName));
- else
- {
- size_t namelen = strlen(FindFileData.cFileName);
- if(namelen > extsize)
- {
- namelen -= extsize;
- if(FindFileData.cFileName[namelen] == '.' && strncmp(FindFileData.cFileName+namelen+1, ext, extsize-1)==0)
- files.add(newstring(FindFileData.cFileName, namelen));
- }
- }
- } while(FindNextFile(Find, &FindFileData));
- FindClose(Find);
- return true;
- }
-#else
- defformatstring(pathname, rel ? "./%s" : "%s", dirname);
- DIR *d = opendir(pathname);
- if(d)
- {
- struct dirent *de;
- while((de = readdir(d)) != NULL)
- {
- if(!ext) files.add(newstring(de->d_name));
- else
- {
- size_t namelen = strlen(de->d_name);
- if(namelen > extsize)
- {
- namelen -= extsize;
- if(de->d_name[namelen] == '.' && strncmp(de->d_name+namelen+1, ext, extsize-1)==0)
- files.add(newstring(de->d_name, namelen));
- }
- }
- }
- closedir(d);
- return true;
- }
-#endif
- else return false;
+ size_t extsize = ext ? strlen(ext)+1 : 0;
+ defformatstring(pathname, rel ? "./%s" : "%s", dirname);
+ DIR *d = opendir(pathname);
+ if(d)
+ {
+ struct dirent *de;
+ while((de = readdir(d)) != NULL)
+ {
+ if(!ext) files.add(newstring(de->d_name));
+ else
+ {
+ size_t namelen = strlen(de->d_name);
+ if(namelen > extsize)
+ {
+ namelen -= extsize;
+ if(de->d_name[namelen] == '.' && strncmp(de->d_name+namelen+1, ext, extsize-1)==0)
+ files.add(newstring(de->d_name, namelen));
+ }
+ }
+ }
+ closedir(d);
+ return true;
+ }
+ else return false;
}
int listfiles(const char *dir, const char *ext, vector<char *> &files)
{
- string dirname;
- copystring(dirname, dir);
- path(dirname);
- size_t dirlen = strlen(dirname);
- while(dirlen > 1 && dirname[dirlen-1] == PATHDIV) dirname[--dirlen] = '\0';
- int dirs = 0;
- if(listdir(dirname, true, ext, files)) dirs++;
- string s;
- if(homedir[0])
- {
- formatstring(s, "%s%s", homedir, dirname);
- if(listdir(s, false, ext, files)) dirs++;
- }
- loopv(packagedirs)
- {
- packagedir &pf = packagedirs[i];
- if(pf.filter && strncmp(dirname, pf.filter, dirlen == pf.filterlen-1 ? dirlen : pf.filterlen))
- continue;
- formatstring(s, "%s%s", pf.dir, dirname);
- if(listdir(s, false, ext, files)) dirs++;
- }
+ string dirname;
+ copystring(dirname, dir);
+ path(dirname);
+ size_t dirlen = strlen(dirname);
+ while(dirlen > 1 && dirname[dirlen-1] == PATHDIV) dirname[--dirlen] = '\0';
+ int dirs = 0;
+ if(listdir(dirname, true, ext, files)) dirs++;
+ string s;
+ if(homedir[0])
+ {
+ formatstring(s, "%s%s", homedir, dirname);
+ if(listdir(s, false, ext, files)) dirs++;
+ }
+ loopv(packagedirs)
+ {
+ packagedir &pf = packagedirs[i];
+ if(pf.filter && strncmp(dirname, pf.filter, dirlen == pf.filterlen-1 ? dirlen : pf.filterlen))
+ continue;
+ formatstring(s, "%s%s", pf.dir, dirname);
+ if(listdir(s, false, ext, files)) dirs++;
+ }
#ifndef STANDALONE
- dirs += listzipfiles(dirname, ext, files);
+ dirs += listzipfiles(dirname, ext, files);
#endif
- return dirs;
+ return dirs;
}
#ifndef STANDALONE
static Sint64 rwopsseek(SDL_RWops *rw, Sint64 pos, int whence)
{
- stream *f = (stream *)rw->hidden.unknown.data1;
- if((!pos && whence==SEEK_CUR) || f->seek(pos, whence)) return (int)f->tell();
- return -1;
+ stream *f = (stream *)rw->hidden.unknown.data1;
+ if((!pos && whence==SEEK_CUR) || f->seek(pos, whence)) return (int)f->tell();
+ return -1;
}
static size_t rwopsread(SDL_RWops *rw, void *buf, size_t size, size_t nmemb)
{
- stream *f = (stream *)rw->hidden.unknown.data1;
- return f->read(buf, size*nmemb)/size;
+ stream *f = (stream *)rw->hidden.unknown.data1;
+ return f->read(buf, size*nmemb)/size;
}
static size_t rwopswrite(SDL_RWops *rw, const void *buf, size_t size, size_t nmemb)
{
- stream *f = (stream *)rw->hidden.unknown.data1;
- return f->write(buf, size*nmemb)/size;
+ stream *f = (stream *)rw->hidden.unknown.data1;
+ return f->write(buf, size*nmemb)/size;
}
static int rwopsclose(SDL_RWops *rw)
{
- return 0;
+ return 0;
}
SDL_RWops *stream::rwops()
{
- SDL_RWops *rw = SDL_AllocRW();
- if(!rw) return NULL;
- rw->hidden.unknown.data1 = this;
- rw->seek = rwopsseek;
- rw->read = rwopsread;
- rw->write = rwopswrite;
- rw->close = rwopsclose;
- return rw;
+ SDL_RWops *rw = SDL_AllocRW();
+ if(!rw) return NULL;
+ rw->hidden.unknown.data1 = this;
+ rw->seek = rwopsseek;
+ rw->read = rwopsread;
+ rw->write = rwopswrite;
+ rw->close = rwopsclose;
+ return rw;
}
#endif
stream::offset stream::size()
{
- offset pos = tell(), endpos;
- if(pos < 0 || !seek(0, SEEK_END)) return -1;
- endpos = tell();
- return pos == endpos || seek(pos, SEEK_SET) ? endpos : -1;
+ offset pos = tell(), endpos;
+ if(pos < 0 || !seek(0, SEEK_END)) return -1;
+ endpos = tell();
+ return pos == endpos || seek(pos, SEEK_SET) ? endpos : -1;
}
bool stream::getline(char *str, size_t len)
{
- loopi(len-1)
- {
- if(read(&str[i], 1) != 1) { str[i] = '\0'; return i > 0; }
- else if(str[i] == '\n') { str[i+1] = '\0'; return true; }
- }
- if(len > 0) str[len-1] = '\0';
- return true;
+ loopi(len-1)
+ {
+ if(read(&str[i], 1) != 1) { str[i] = '\0'; return i > 0; }
+ else if(str[i] == '\n') { str[i+1] = '\0'; return true; }
+ }
+ if(len > 0) str[len-1] = '\0';
+ return true;
}
size_t stream::printf(const char *fmt, ...)
{
- char buf[512];
- char *str = buf;
- va_list args;
- va_start(args, fmt);
- int len = vsnprintf(buf, sizeof(buf), fmt, args);
- va_end(args);
- if(len <= 0) return 0;
- if(len >= (int)sizeof(buf))
- {
- str = new char[len+1];
- va_start(args, fmt);
- vsnprintf(str, len+1, fmt, args);
- va_end(args);
- }
- size_t n = write(str, len);
- if(str != buf) delete[] str;
- return n;
+ char buf[512];
+ char *str = buf;
+ va_list args;
+ va_start(args, fmt);
+ int len = vsnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+ if(len <= 0) return 0;
+ if(len >= (int)sizeof(buf))
+ {
+ str = new char[len+1];
+ va_start(args, fmt);
+ vsnprintf(str, len+1, fmt, args);
+ va_end(args);
+ }
+ size_t n = write(str, len);
+ if(str != buf) delete[] str;
+ return n;
}
struct filestream : stream
{
- FILE *file;
-
- filestream() : file(NULL) {}
- ~filestream() { close(); }
-
- bool open(const char *name, const char *mode)
- {
- if(file) return false;
- file = fopen(name, mode);
- return file!=NULL;
- }
-
- bool opentemp(const char *name, const char *mode)
- {
- if(file) return false;
- file = tmpfile();
- return file!=NULL;
- }
-
- void close()
- {
- if(file) { fclose(file); file = NULL; }
- }
-
- bool end() { return feof(file)!=0; }
- offset tell()
- {
- offset off = ftello(file);
- return off + 1 >= 0 ? off : -1;
- }
- bool seek(offset pos, int whence = SEEK_SET)
- {
- return fseeko(file, pos, whence) >= 0;
- }
-
- size_t read(void *buf, size_t len) { return fread(buf, 1, len, file); }
- size_t write(const void *buf, size_t len) { return fwrite(buf, 1, len, file); }
- bool flush() { return !fflush(file); }
- int getchar() { return fgetc(file); }
- bool putchar(int c) { return fputc(c, file)!=EOF; }
- bool getline(char *str, size_t len) { return fgets(str, len, file)!=NULL; }
- bool putstring(const char *str) { return fputs(str, file)!=EOF; }
-
- size_t printf(const char *fmt, ...)
- {
- va_list v;
- va_start(v, fmt);
- int result = vfprintf(file, fmt, v);
- va_end(v);
- return max(result, 0);
- }
+ FILE *file;
+
+ filestream() : file(NULL) {}
+ ~filestream() { close(); }
+
+ bool open(const char *name, const char *mode)
+ {
+ if(file) return false;
+ file = fopen(name, mode);
+ return file!=NULL;
+ }
+
+ bool opentemp(const char *name, const char *mode)
+ {
+ if(file) return false;
+ file = tmpfile();
+ return file!=NULL;
+ }
+
+ void close()
+ {
+ if(file) { fclose(file); file = NULL; }
+ }
+
+ bool end() { return feof(file)!=0; }
+ offset tell()
+ {
+ offset off = ftello(file);
+ return off + 1 >= 0 ? off : -1;
+ }
+ bool seek(offset pos, int whence = SEEK_SET)
+ {
+ return fseeko(file, pos, whence) >= 0;
+ }
+
+ size_t read(void *buf, size_t len) { return fread(buf, 1, len, file); }
+ size_t write(const void *buf, size_t len) { return fwrite(buf, 1, len, file); }
+ bool flush() { return !fflush(file); }
+ int getchar() { return fgetc(file); }
+ bool putchar(int c) { return fputc(c, file)!=EOF; }
+ bool getline(char *str, size_t len) { return fgets(str, len, file)!=NULL; }
+ bool putstring(const char *str) { return fputs(str, file)!=EOF; }
+
+ size_t printf(const char *fmt, ...)
+ {
+ va_list v;
+ va_start(v, fmt);
+ int result = vfprintf(file, fmt, v);
+ va_end(v);
+ return max(result, 0);
+ }
};
struct gzstream : stream
{
- enum
- {
- MAGIC1 = 0x1F,
- MAGIC2 = 0x8B,
- BUFSIZE = 16384,
- OS_UNIX = 0x03
- };
-
- enum
- {
- F_ASCII = 0x01,
- F_CRC = 0x02,
- F_EXTRA = 0x04,
- F_NAME = 0x08,
- F_COMMENT = 0x10,
- F_RESERVED = 0xE0
- };
-
- stream *file;
- z_stream zfile;
- uchar *buf;
- bool reading, writing, autoclose;
- uint crc;
- size_t headersize;
-
- gzstream() : file(NULL), buf(NULL), reading(false), writing(false), autoclose(false), crc(0), headersize(0)
- {
- zfile.zalloc = NULL;
- zfile.zfree = NULL;
- zfile.opaque = NULL;
- zfile.next_in = zfile.next_out = NULL;
- zfile.avail_in = zfile.avail_out = 0;
- }
-
- ~gzstream()
- {
- close();
- }
-
- void writeheader()
- {
- uchar header[] = { MAGIC1, MAGIC2, Z_DEFLATED, 0, 0, 0, 0, 0, 0, OS_UNIX };
- file->write(header, sizeof(header));
- }
-
- void readbuf(size_t size = BUFSIZE)
- {
- if(!zfile.avail_in) zfile.next_in = (Bytef *)buf;
- size = min(size, size_t(&buf[BUFSIZE] - &zfile.next_in[zfile.avail_in]));
- size_t n = file->read(zfile.next_in + zfile.avail_in, size);
- if(n > 0) zfile.avail_in += n;
- }
-
- uchar readbyte(size_t size = BUFSIZE)
- {
- if(!zfile.avail_in) readbuf(size);
- if(!zfile.avail_in) return 0;
- zfile.avail_in--;
- return *(uchar *)zfile.next_in++;
- }
-
- void skipbytes(size_t n)
- {
- while(n > 0 && zfile.avail_in > 0)
- {
- size_t skipped = min(n, size_t(zfile.avail_in));
- zfile.avail_in -= skipped;
- zfile.next_in += skipped;
- n -= skipped;
- }
- if(n <= 0) return;
- file->seek(n, SEEK_CUR);
- }
-
- bool checkheader()
- {
- readbuf(10);
- if(readbyte() != MAGIC1 || readbyte() != MAGIC2 || readbyte() != Z_DEFLATED) return false;
- uchar flags = readbyte();
- if(flags & F_RESERVED) return false;
- skipbytes(6);
- if(flags & F_EXTRA)
- {
- size_t len = readbyte(512);
- len |= size_t(readbyte(512))<<8;
- skipbytes(len);
- }
- if(flags & F_NAME) while(readbyte(512));
- if(flags & F_COMMENT) while(readbyte(512));
- if(flags & F_CRC) skipbytes(2);
- headersize = size_t(file->tell() - zfile.avail_in);
- return zfile.avail_in > 0 || !file->end();
- }
-
- bool open(stream *f, const char *mode, bool needclose, int level)
- {
- if(file) return false;
- for(; *mode; mode++)
- {
- if(*mode=='r') { reading = true; break; }
- else if(*mode=='w') { writing = true; break; }
- }
- if(reading)
- {
- if(inflateInit2(&zfile, -MAX_WBITS) != Z_OK) reading = false;
- }
- else if(writing && deflateInit2(&zfile, level, Z_DEFLATED, -MAX_WBITS, min(MAX_MEM_LEVEL, 8), Z_DEFAULT_STRATEGY) != Z_OK) writing = false;
- if(!reading && !writing) return false;
-
- file = f;
- crc = crc32(0, NULL, 0);
- buf = new uchar[BUFSIZE];
-
- if(reading)
- {
- if(!checkheader()) { stopreading(); return false; }
- }
- else if(writing) writeheader();
-
- autoclose = needclose;
- return true;
- }
-
- uint getcrc() { return crc; }
-
- void finishreading()
- {
- if(!reading) return;
- }
-
- void stopreading()
- {
- if(!reading) return;
- inflateEnd(&zfile);
- reading = false;
- }
-
- void finishwriting()
- {
- if(!writing) return;
- for(;;)
- {
- int err = zfile.avail_out > 0 ? deflate(&zfile, Z_FINISH) : Z_OK;
- if(err != Z_OK && err != Z_STREAM_END) break;
- flushbuf();
- if(err == Z_STREAM_END) break;
- }
- uchar trailer[8] =
- {
- uchar(crc&0xFF), uchar((crc>>8)&0xFF), uchar((crc>>16)&0xFF), uchar((crc>>24)&0xFF),
- uchar(zfile.total_in&0xFF), uchar((zfile.total_in>>8)&0xFF), uchar((zfile.total_in>>16)&0xFF), uchar((zfile.total_in>>24)&0xFF)
- };
- file->write(trailer, sizeof(trailer));
- }
-
- void stopwriting()
- {
- if(!writing) return;
- deflateEnd(&zfile);
- writing = false;
- }
-
- void close()
- {
- if(reading) finishreading();
- stopreading();
- if(writing) finishwriting();
- stopwriting();
- DELETEA(buf);
- if(autoclose) DELETEP(file);
- }
-
- bool end() { return !reading && !writing; }
- offset tell() { return reading ? zfile.total_out : (writing ? zfile.total_in : offset(-1)); }
- offset rawtell() { return file ? file->tell() : offset(-1); }
-
- offset size()
- {
- if(!file) return -1;
- offset pos = tell();
- if(!file->seek(-4, SEEK_END)) return -1;
- uint isize = file->getlil<uint>();
- return file->seek(pos, SEEK_SET) ? isize : offset(-1);
- }
-
- offset rawsize() { return file ? file->size() : offset(-1); }
-
- bool seek(offset pos, int whence)
- {
- if(writing || !reading) return false;
-
- if(whence == SEEK_END)
- {
- uchar skip[512];
- while(read(skip, sizeof(skip)) == sizeof(skip));
- return !pos;
- }
- else if(whence == SEEK_CUR) pos += zfile.total_out;
-
- if(pos >= (offset)zfile.total_out) pos -= zfile.total_out;
- else if(pos < 0 || !file->seek(headersize, SEEK_SET)) return false;
- else
- {
- if(zfile.next_in && zfile.total_in <= uint(zfile.next_in - buf))
- {
- zfile.avail_in += zfile.total_in;
- zfile.next_in -= zfile.total_in;
- }
- else
- {
- zfile.avail_in = 0;
- zfile.next_in = NULL;
- }
- inflateReset(&zfile);
- crc = crc32(0, NULL, 0);
- }
-
- uchar skip[512];
- while(pos > 0)
- {
- size_t skipped = (size_t)min(pos, (offset)sizeof(skip));
- if(read(skip, skipped) != skipped) { stopreading(); return false; }
- pos -= skipped;
- }
-
- return true;
- }
-
- size_t read(void *buf, size_t len)
- {
- if(!reading || !buf || !len) return 0;
- zfile.next_out = (Bytef *)buf;
- zfile.avail_out = len;
- while(zfile.avail_out > 0)
- {
- if(!zfile.avail_in)
- {
- readbuf(BUFSIZE);
- if(!zfile.avail_in) { stopreading(); break; }
- }
- int err = inflate(&zfile, Z_NO_FLUSH);
- if(err == Z_STREAM_END) { crc = crc32(crc, (Bytef *)buf, len - zfile.avail_out); finishreading(); stopreading(); return len - zfile.avail_out; }
- else if(err != Z_OK) { stopreading(); break; }
- }
- crc = crc32(crc, (Bytef *)buf, len - zfile.avail_out);
- return len - zfile.avail_out;
- }
-
- bool flushbuf(bool full = false)
- {
- if(full) deflate(&zfile, Z_SYNC_FLUSH);
- if(zfile.next_out && zfile.avail_out < BUFSIZE)
- {
- if(file->write(buf, BUFSIZE - zfile.avail_out) != BUFSIZE - zfile.avail_out || (full && !file->flush()))
- return false;
- }
- zfile.next_out = buf;
- zfile.avail_out = BUFSIZE;
- return true;
- }
-
- bool flush() { return flushbuf(true); }
-
- size_t write(const void *buf, size_t len)
- {
- if(!writing || !buf || !len) return 0;
- zfile.next_in = (Bytef *)buf;
- zfile.avail_in = len;
- while(zfile.avail_in > 0)
- {
- if(!zfile.avail_out && !flushbuf()) { stopwriting(); break; }
- int err = deflate(&zfile, Z_NO_FLUSH);
- if(err != Z_OK) { stopwriting(); break; }
- }
- crc = crc32(crc, (Bytef *)buf, len - zfile.avail_in);
- return len - zfile.avail_in;
- }
+ enum
+ {
+ MAGIC1 = 0x1F,
+ MAGIC2 = 0x8B,
+ BUFSIZE = 16384,
+ OS_UNIX = 0x03
+ };
+
+ enum
+ {
+ F_ASCII = 0x01,
+ F_CRC = 0x02,
+ F_EXTRA = 0x04,
+ F_NAME = 0x08,
+ F_COMMENT = 0x10,
+ F_RESERVED = 0xE0
+ };
+
+ stream *file;
+ z_stream zfile;
+ uchar *buf;
+ bool reading, writing, autoclose;
+ uint crc;
+ size_t headersize;
+
+ gzstream() : file(NULL), buf(NULL), reading(false), writing(false), autoclose(false), crc(0), headersize(0)
+ {
+ zfile.zalloc = NULL;
+ zfile.zfree = NULL;
+ zfile.opaque = NULL;
+ zfile.next_in = zfile.next_out = NULL;
+ zfile.avail_in = zfile.avail_out = 0;
+ }
+
+ ~gzstream()
+ {
+ close();
+ }
+
+ void writeheader()
+ {
+ uchar header[] = { MAGIC1, MAGIC2, Z_DEFLATED, 0, 0, 0, 0, 0, 0, OS_UNIX };
+ file->write(header, sizeof(header));
+ }
+
+ void readbuf(size_t size = BUFSIZE)
+ {
+ if(!zfile.avail_in) zfile.next_in = (Bytef *)buf;
+ size = min(size, size_t(&buf[BUFSIZE] - &zfile.next_in[zfile.avail_in]));
+ size_t n = file->read(zfile.next_in + zfile.avail_in, size);
+ if(n > 0) zfile.avail_in += n;
+ }
+
+ uchar readbyte(size_t size = BUFSIZE)
+ {
+ if(!zfile.avail_in) readbuf(size);
+ if(!zfile.avail_in) return 0;
+ zfile.avail_in--;
+ return *(uchar *)zfile.next_in++;
+ }
+
+ void skipbytes(size_t n)
+ {
+ while(n > 0 && zfile.avail_in > 0)
+ {
+ size_t skipped = min(n, size_t(zfile.avail_in));
+ zfile.avail_in -= skipped;
+ zfile.next_in += skipped;
+ n -= skipped;
+ }
+ if(n <= 0) return;
+ file->seek(n, SEEK_CUR);
+ }
+
+ bool checkheader()
+ {
+ readbuf(10);
+ if(readbyte() != MAGIC1 || readbyte() != MAGIC2 || readbyte() != Z_DEFLATED) return false;
+ uchar flags = readbyte();
+ if(flags & F_RESERVED) return false;
+ skipbytes(6);
+ if(flags & F_EXTRA)
+ {
+ size_t len = readbyte(512);
+ len |= size_t(readbyte(512))<<8;
+ skipbytes(len);
+ }
+ if(flags & F_NAME) while(readbyte(512));
+ if(flags & F_COMMENT) while(readbyte(512));
+ if(flags & F_CRC) skipbytes(2);
+ headersize = size_t(file->tell() - zfile.avail_in);
+ return zfile.avail_in > 0 || !file->end();
+ }
+
+ bool open(stream *f, const char *mode, bool needclose, int level)
+ {
+ if(file) return false;
+ for(; *mode; mode++)
+ {
+ if(*mode=='r') { reading = true; break; }
+ else if(*mode=='w') { writing = true; break; }
+ }
+ if(reading)
+ {
+ if(inflateInit2(&zfile, -MAX_WBITS) != Z_OK) reading = false;
+ }
+ else if(writing && deflateInit2(&zfile, level, Z_DEFLATED, -MAX_WBITS, min(MAX_MEM_LEVEL, 8), Z_DEFAULT_STRATEGY) != Z_OK) writing = false;
+ if(!reading && !writing) return false;
+
+ file = f;
+ crc = crc32(0, NULL, 0);
+ buf = new uchar[BUFSIZE];
+
+ if(reading)
+ {
+ if(!checkheader()) { stopreading(); return false; }
+ }
+ else if(writing) writeheader();
+
+ autoclose = needclose;
+ return true;
+ }
+
+ uint getcrc() { return crc; }
+
+ void finishreading()
+ {
+ if(!reading) return;
+ }
+
+ void stopreading()
+ {
+ if(!reading) return;
+ inflateEnd(&zfile);
+ reading = false;
+ }
+
+ void finishwriting()
+ {
+ if(!writing) return;
+ for(;;)
+ {
+ int err = zfile.avail_out > 0 ? deflate(&zfile, Z_FINISH) : Z_OK;
+ if(err != Z_OK && err != Z_STREAM_END) break;
+ flushbuf();
+ if(err == Z_STREAM_END) break;
+ }
+ uchar trailer[8] =
+ {
+ uchar(crc&0xFF), uchar((crc>>8)&0xFF), uchar((crc>>16)&0xFF), uchar((crc>>24)&0xFF),
+ uchar(zfile.total_in&0xFF), uchar((zfile.total_in>>8)&0xFF), uchar((zfile.total_in>>16)&0xFF), uchar((zfile.total_in>>24)&0xFF)
+ };
+ file->write(trailer, sizeof(trailer));
+ }
+
+ void stopwriting()
+ {
+ if(!writing) return;
+ deflateEnd(&zfile);
+ writing = false;
+ }
+
+ void close()
+ {
+ if(reading) finishreading();
+ stopreading();
+ if(writing) finishwriting();
+ stopwriting();
+ DELETEA(buf);
+ if(autoclose) DELETEP(file);
+ }
+
+ bool end() { return !reading && !writing; }
+ offset tell() { return reading ? zfile.total_out : (writing ? zfile.total_in : offset(-1)); }
+ offset rawtell() { return file ? file->tell() : offset(-1); }
+
+ offset size()
+ {
+ if(!file) return -1;
+ offset pos = tell();
+ if(!file->seek(-4, SEEK_END)) return -1;
+ uint isize = file->getlil<uint>();
+ return file->seek(pos, SEEK_SET) ? isize : offset(-1);
+ }
+
+ offset rawsize() { return file ? file->size() : offset(-1); }
+
+ bool seek(offset pos, int whence)
+ {
+ if(writing || !reading) return false;
+
+ if(whence == SEEK_END)
+ {
+ uchar skip[512];
+ while(read(skip, sizeof(skip)) == sizeof(skip));
+ return !pos;
+ }
+ else if(whence == SEEK_CUR) pos += zfile.total_out;
+
+ if(pos >= (offset)zfile.total_out) pos -= zfile.total_out;
+ else if(pos < 0 || !file->seek(headersize, SEEK_SET)) return false;
+ else
+ {
+ if(zfile.next_in && zfile.total_in <= uint(zfile.next_in - buf))
+ {
+ zfile.avail_in += zfile.total_in;
+ zfile.next_in -= zfile.total_in;
+ }
+ else
+ {
+ zfile.avail_in = 0;
+ zfile.next_in = NULL;
+ }
+ inflateReset(&zfile);
+ crc = crc32(0, NULL, 0);
+ }
+
+ uchar skip[512];
+ while(pos > 0)
+ {
+ size_t skipped = (size_t)min(pos, (offset)sizeof(skip));
+ if(read(skip, skipped) != skipped) { stopreading(); return false; }
+ pos -= skipped;
+ }
+
+ return true;
+ }
+
+ size_t read(void *buf, size_t len)
+ {
+ if(!reading || !buf || !len) return 0;
+ zfile.next_out = (Bytef *)buf;
+ zfile.avail_out = len;
+ while(zfile.avail_out > 0)
+ {
+ if(!zfile.avail_in)
+ {
+ readbuf(BUFSIZE);
+ if(!zfile.avail_in) { stopreading(); break; }
+ }
+ int err = inflate(&zfile, Z_NO_FLUSH);
+ if(err == Z_STREAM_END) { crc = crc32(crc, (Bytef *)buf, len - zfile.avail_out); finishreading(); stopreading(); return len - zfile.avail_out; }
+ else if(err != Z_OK) { stopreading(); break; }
+ }
+ crc = crc32(crc, (Bytef *)buf, len - zfile.avail_out);
+ return len - zfile.avail_out;
+ }
+
+ bool flushbuf(bool full = false)
+ {
+ if(full) deflate(&zfile, Z_SYNC_FLUSH);
+ if(zfile.next_out && zfile.avail_out < BUFSIZE)
+ {
+ if(file->write(buf, BUFSIZE - zfile.avail_out) != BUFSIZE - zfile.avail_out || (full && !file->flush()))
+ return false;
+ }
+ zfile.next_out = buf;
+ zfile.avail_out = BUFSIZE;
+ return true;
+ }
+
+ bool flush() { return flushbuf(true); }
+
+ size_t write(const void *buf, size_t len)
+ {
+ if(!writing || !buf || !len) return 0;
+ zfile.next_in = (Bytef *)buf;
+ zfile.avail_in = len;
+ while(zfile.avail_in > 0)
+ {
+ if(!zfile.avail_out && !flushbuf()) { stopwriting(); break; }
+ int err = deflate(&zfile, Z_NO_FLUSH);
+ if(err != Z_OK) { stopwriting(); break; }
+ }
+ crc = crc32(crc, (Bytef *)buf, len - zfile.avail_in);
+ return len - zfile.avail_in;
+ }
};
struct utf8stream : stream
{
- enum
- {
- BUFSIZE = 4096
- };
- stream *file;
- offset pos;
- size_t bufread, bufcarry, buflen;
- bool reading, writing, autoclose;
- uchar buf[BUFSIZE];
-
- utf8stream() : file(NULL), pos(0), bufread(0), bufcarry(0), buflen(0), reading(false), writing(false), autoclose(false)
- {
- }
-
- ~utf8stream()
- {
- close();
- }
-
- bool readbuf(size_t size = BUFSIZE)
- {
- if(bufread >= bufcarry) { if(bufcarry > 0 && bufcarry < buflen) memmove(buf, &buf[bufcarry], buflen - bufcarry); buflen -= bufcarry; bufread = bufcarry = 0; }
- size_t n = file->read(&buf[buflen], min(size, BUFSIZE - buflen));
- if(n <= 0) return false;
- buflen += n;
- size_t carry = bufcarry;
- bufcarry += decodeutf8(&buf[bufcarry], BUFSIZE-bufcarry, &buf[bufcarry], buflen-bufcarry, &carry);
- if(carry > bufcarry && carry < buflen) { memmove(&buf[bufcarry], &buf[carry], buflen - carry); buflen -= carry - bufcarry; }
- return true;
- }
-
- bool checkheader()
- {
- size_t n = file->read(buf, 3);
- if(n == 3 && buf[0] == 0xEF && buf[1] == 0xBB && buf[2] == 0xBF) return true;
- buflen = n;
- return false;
- }
-
- bool open(stream *f, const char *mode, bool needclose)
- {
- if(file) return false;
- for(; *mode; mode++)
- {
- if(*mode=='r') { reading = true; break; }
- else if(*mode=='w') { writing = true; break; }
- }
- if(!reading && !writing) return false;
-
- file = f;
-
- if(reading) checkheader();
-
- autoclose = needclose;
- return true;
- }
-
- void finishreading()
- {
- if(!reading) return;
- }
-
- void stopreading()
- {
- if(!reading) return;
- reading = false;
- }
-
- void stopwriting()
- {
- if(!writing) return;
- writing = false;
- }
-
- void close()
- {
- stopreading();
- stopwriting();
- if(autoclose) DELETEP(file);
- }
-
- bool end() { return !reading && !writing; }
- offset tell() { return reading || writing ? pos : offset(-1); }
-
- bool seek(offset off, int whence)
- {
- if(writing || !reading) return false;
-
- if(whence == SEEK_END)
- {
- uchar skip[512];
- while(read(skip, sizeof(skip)) == sizeof(skip));
- return !off;
- }
- else if(whence == SEEK_CUR) off += pos;
-
- if(off >= pos) off -= pos;
- else if(off < 0 || !file->seek(0, SEEK_SET)) return false;
- else
- {
- bufread = bufcarry = buflen = 0;
- pos = 0;
- checkheader();
- }
-
- uchar skip[512];
- while(off > 0)
- {
- size_t skipped = (size_t)min(off, (offset)sizeof(skip));
- if(read(skip, skipped) != skipped) { stopreading(); return false; }
- off -= skipped;
- }
-
- return true;
- }
-
- size_t read(void *dst, size_t len)
- {
- if(!reading || !dst || !len) return 0;
- size_t next = 0;
- while(next < len)
- {
- if(bufread >= bufcarry) { if(readbuf(BUFSIZE)) continue; stopreading(); break; }
- size_t n = min(len - next, bufcarry - bufread);
- memcpy(&((uchar *)dst)[next], &buf[bufread], n);
- next += n;
- bufread += n;
- }
- pos += next;
- return next;
- }
-
- bool getline(char *dst, size_t len)
- {
- if(!reading || !dst || !len) return false;
- --len;
- size_t next = 0;
- while(next < len)
- {
- if(bufread >= bufcarry) { if(readbuf(BUFSIZE)) continue; stopreading(); if(!next) return false; break; }
- size_t n = min(len - next, bufcarry - bufread);
- uchar *endline = (uchar *)memchr(&buf[bufread], '\n', n);
- if(endline) { n = endline+1 - &buf[bufread]; len = next + n; }
- memcpy(&((uchar *)dst)[next], &buf[bufread], n);
- next += n;
- bufread += n;
- }
- dst[next] = '\0';
- pos += next;
- return true;
- }
-
- size_t write(const void *src, size_t len)
- {
- if(!writing || !src || !len) return 0;
- uchar dst[512];
- size_t next = 0;
- while(next < len)
- {
- size_t carry = 0, n = encodeutf8(dst, sizeof(dst), &((uchar *)src)[next], len - next, &carry);
- if(n > 0 && file->write(dst, n) != n) { stopwriting(); break; }
- next += carry;
- }
- pos += next;
- return next;
- }
-
- bool flush() { return file->flush(); }
+ enum
+ {
+ BUFSIZE = 4096
+ };
+ stream *file;
+ offset pos;
+ size_t bufread, bufcarry, buflen;
+ bool reading, writing, autoclose;
+ uchar buf[BUFSIZE];
+
+ utf8stream() : file(NULL), pos(0), bufread(0), bufcarry(0), buflen(0), reading(false), writing(false), autoclose(false)
+ {
+ }
+
+ ~utf8stream()
+ {
+ close();
+ }
+
+ bool readbuf(size_t size = BUFSIZE)
+ {
+ if(bufread >= bufcarry) { if(bufcarry > 0 && bufcarry < buflen) memmove(buf, &buf[bufcarry], buflen - bufcarry); buflen -= bufcarry; bufread = bufcarry = 0; }
+ size_t n = file->read(&buf[buflen], min(size, BUFSIZE - buflen));
+ if(n <= 0) return false;
+ buflen += n;
+ size_t carry = bufcarry;
+ bufcarry += decodeutf8(&buf[bufcarry], BUFSIZE-bufcarry, &buf[bufcarry], buflen-bufcarry, &carry);
+ if(carry > bufcarry && carry < buflen) { memmove(&buf[bufcarry], &buf[carry], buflen - carry); buflen -= carry - bufcarry; }
+ return true;
+ }
+
+ bool checkheader()
+ {
+ size_t n = file->read(buf, 3);
+ if(n == 3 && buf[0] == 0xEF && buf[1] == 0xBB && buf[2] == 0xBF) return true;
+ buflen = n;
+ return false;
+ }
+
+ bool open(stream *f, const char *mode, bool needclose)
+ {
+ if(file) return false;
+ for(; *mode; mode++)
+ {
+ if(*mode=='r') { reading = true; break; }
+ else if(*mode=='w') { writing = true; break; }
+ }
+ if(!reading && !writing) return false;
+
+ file = f;
+
+ if(reading) checkheader();
+
+ autoclose = needclose;
+ return true;
+ }
+
+ void finishreading()
+ {
+ if(!reading) return;
+ }
+
+ void stopreading()
+ {
+ if(!reading) return;
+ reading = false;
+ }
+
+ void stopwriting()
+ {
+ if(!writing) return;
+ writing = false;
+ }
+
+ void close()
+ {
+ stopreading();
+ stopwriting();
+ if(autoclose) DELETEP(file);
+ }
+
+ bool end() { return !reading && !writing; }
+ offset tell() { return reading || writing ? pos : offset(-1); }
+
+ bool seek(offset off, int whence)
+ {
+ if(writing || !reading) return false;
+
+ if(whence == SEEK_END)
+ {
+ uchar skip[512];
+ while(read(skip, sizeof(skip)) == sizeof(skip));
+ return !off;
+ }
+ else if(whence == SEEK_CUR) off += pos;
+
+ if(off >= pos) off -= pos;
+ else if(off < 0 || !file->seek(0, SEEK_SET)) return false;
+ else
+ {
+ bufread = bufcarry = buflen = 0;
+ pos = 0;
+ checkheader();
+ }
+
+ uchar skip[512];
+ while(off > 0)
+ {
+ size_t skipped = (size_t)min(off, (offset)sizeof(skip));
+ if(read(skip, skipped) != skipped) { stopreading(); return false; }
+ off -= skipped;
+ }
+
+ return true;
+ }
+
+ size_t read(void *dst, size_t len)
+ {
+ if(!reading || !dst || !len) return 0;
+ size_t next = 0;
+ while(next < len)
+ {
+ if(bufread >= bufcarry) { if(readbuf(BUFSIZE)) continue; stopreading(); break; }
+ size_t n = min(len - next, bufcarry - bufread);
+ memcpy(&((uchar *)dst)[next], &buf[bufread], n);
+ next += n;
+ bufread += n;
+ }
+ pos += next;
+ return next;
+ }
+
+ bool getline(char *dst, size_t len)
+ {
+ if(!reading || !dst || !len) return false;
+ --len;
+ size_t next = 0;
+ while(next < len)
+ {
+ if(bufread >= bufcarry) { if(readbuf(BUFSIZE)) continue; stopreading(); if(!next) return false; break; }
+ size_t n = min(len - next, bufcarry - bufread);
+ uchar *endline = (uchar *)memchr(&buf[bufread], '\n', n);
+ if(endline) { n = endline+1 - &buf[bufread]; len = next + n; }
+ memcpy(&((uchar *)dst)[next], &buf[bufread], n);
+ next += n;
+ bufread += n;
+ }
+ dst[next] = '\0';
+ pos += next;
+ return true;
+ }
+
+ size_t write(const void *src, size_t len)
+ {
+ if(!writing || !src || !len) return 0;
+ uchar dst[512];
+ size_t next = 0;
+ while(next < len)
+ {
+ size_t carry = 0, n = encodeutf8(dst, sizeof(dst), &((uchar *)src)[next], len - next, &carry);
+ if(n > 0 && file->write(dst, n) != n) { stopwriting(); break; }
+ next += carry;
+ }
+ pos += next;
+ return next;
+ }
+
+ bool flush() { return file->flush(); }
};
stream *openrawfile(const char *filename, const char *mode)
{
- const char *found = findfile(filename, mode);
- if(!found) return NULL;
- filestream *file = new filestream;
- if(!file->open(found, mode)) { delete file; return NULL; }
- return file;
+ const char *found = findfile(filename, mode);
+ if(!found) return NULL;
+ filestream *file = new filestream;
+ if(!file->open(found, mode)) { delete file; return NULL; }
+ return file;
}
stream *openfile(const char *filename, const char *mode)
{
#ifndef STANDALONE
- stream *s = openzipfile(filename, mode);
- if(s) return s;
+ stream *s = openzipfile(filename, mode);
+ if(s) return s;
#endif
- return openrawfile(filename, mode);
+ return openrawfile(filename, mode);
}
stream *opentempfile(const char *name, const char *mode)
{
- const char *found = findfile(name, mode);
- filestream *file = new filestream;
- if(!file->opentemp(found ? found : name, mode)) { delete file; return NULL; }
- return file;
+ const char *found = findfile(name, mode);
+ filestream *file = new filestream;
+ if(!file->opentemp(found ? found : name, mode)) { delete file; return NULL; }
+ return file;
}
stream *opengzfile(const char *filename, const char *mode, stream *file, int level)
{
- stream *source = file ? file : openfile(filename, mode);
- if(!source) return NULL;
- gzstream *gz = new gzstream;
- if(!gz->open(source, mode, !file, level)) { if(!file) delete source; delete gz; return NULL; }
- return gz;
+ stream *source = file ? file : openfile(filename, mode);
+ if(!source) return NULL;
+ gzstream *gz = new gzstream;
+ if(!gz->open(source, mode, !file, level)) { if(!file) delete source; delete gz; return NULL; }
+ return gz;
}
stream *openutf8file(const char *filename, const char *mode, stream *file)
{
- stream *source = file ? file : openfile(filename, mode);
- if(!source) return NULL;
- utf8stream *utf8 = new utf8stream;
- if(!utf8->open(source, mode, !file)) { if(!file) delete source; delete utf8; return NULL; }
- return utf8;
+ stream *source = file ? file : openfile(filename, mode);
+ if(!source) return NULL;
+ utf8stream *utf8 = new utf8stream;
+ if(!utf8->open(source, mode, !file)) { if(!file) delete source; delete utf8; return NULL; }
+ return utf8;
}
char *loadfile(const char *fn, size_t *size, bool utf8)
{
- stream *f = openfile(fn, "rb");
- if(!f) return NULL;
- stream::offset fsize = f->size();
- if(fsize <= 0) { delete f; return NULL; }
- size_t len = fsize;
- char *buf = new (false) char[len+1];
- if(!buf) { delete f; return NULL; }
- size_t offset = 0;
- if(utf8 && len >= 3)
- {
- if(f->read(buf, 3) != 3) { delete f; delete[] buf; return NULL; }
- if(((uchar *)buf)[0] == 0xEF && ((uchar *)buf)[1] == 0xBB && ((uchar *)buf)[2] == 0xBF) len -= 3;
- else offset += 3;
- }
- size_t rlen = f->read(&buf[offset], len-offset);
- delete f;
- if(rlen != len-offset) { delete[] buf; return NULL; }
- if(utf8) len = decodeutf8((uchar *)buf, len, (uchar *)buf, len);
- buf[len] = '\0';
- if(size!=NULL) *size = len;
- return buf;
+ stream *f = openfile(fn, "rb");
+ if(!f) return NULL;
+ stream::offset fsize = f->size();
+ if(fsize <= 0) { delete f; return NULL; }
+ size_t len = fsize;
+ char *buf = new (false) char[len+1];
+ if(!buf) { delete f; return NULL; }
+ size_t offset = 0;
+ if(utf8 && len >= 3)
+ {
+ if(f->read(buf, 3) != 3) { delete f; delete[] buf; return NULL; }
+ if(((uchar *)buf)[0] == 0xEF && ((uchar *)buf)[1] == 0xBB && ((uchar *)buf)[2] == 0xBF) len -= 3;
+ else offset += 3;
+ }
+ size_t rlen = f->read(&buf[offset], len-offset);
+ delete f;
+ if(rlen != len-offset) { delete[] buf; return NULL; }
+ if(utf8) len = decodeutf8((uchar *)buf, len, (uchar *)buf, len);
+ buf[len] = '\0';
+ if(size!=NULL) *size = len;
+ return buf;
}
diff --git a/src/shared/tools.cpp b/src/shared/tools.cpp
index 0ae7559..1b49a8c 100644
--- a/src/shared/tools.cpp
+++ b/src/shared/tools.cpp
@@ -4,16 +4,16 @@
void *operator new(size_t size)
{
- void *p = malloc(size);
- if(!p) abort();
- return p;
+ void *p = malloc(size);
+ if(!p) abort();
+ return p;
}
void *operator new[](size_t size)
{
- void *p = malloc(size);
- if(!p) abort();
- return p;
+ void *p = malloc(size);
+ if(!p) abort();
+ return p;
}
void operator delete(void *p) { if(p) free(p); }
@@ -24,16 +24,16 @@ void operator delete[](void *p, size_t n) { (void) n; if(p) free(p); }
void *operator new(size_t size, bool err)
{
- void *p = malloc(size);
- if(!p && err) abort();
- return p;
+ void *p = malloc(size);
+ if(!p && err) abort();
+ return p;
}
void *operator new[](size_t size, bool err)
{
- void *p = malloc(size);
- if(!p && err) abort();
- return p;
+ void *p = malloc(size);
+ if(!p && err) abort();
+ return p;
}
////////////////////////// rnd numbers ////////////////////////////////////////
@@ -47,27 +47,27 @@ static int next = N;
void seedMT(uint seed)
{
- state[0] = seed;
- for(uint i = 1; i < N; i++)
- state[i] = seed = 1812433253U * (seed ^ (seed >> 30)) + i;
- next = 0;
+ state[0] = seed;
+ for(uint i = 1; i < N; i++)
+ state[i] = seed = 1812433253U * (seed ^ (seed >> 30)) + i;
+ next = 0;
}
uint randomMT()
{
- int cur = next;
- if(++next >= N)
- {
- if(next > N) { seedMT(5489U + time(NULL)); cur = next++; }
- else next = 0;
- }
- uint y = (state[cur] & 0x80000000U) | (state[next] & 0x7FFFFFFFU);
- state[cur] = y = state[cur < N-M ? cur + M : cur + M-N] ^ (y >> 1) ^ (-int(y & 1U) & K);
- y ^= (y >> 11);
- y ^= (y << 7) & 0x9D2C5680U;
- y ^= (y << 15) & 0xEFC60000U;
- y ^= (y >> 18);
- return y;
+ int cur = next;
+ if(++next >= N)
+ {
+ if(next > N) { seedMT(5489U + time(NULL)); cur = next++; }
+ else next = 0;
+ }
+ uint y = (state[cur] & 0x80000000U) | (state[next] & 0x7FFFFFFFU);
+ state[cur] = y = state[cur < N-M ? cur + M : cur + M-N] ^ (y >> 1) ^ (-int(y & 1U) & K);
+ y ^= (y >> 11);
+ y ^= (y << 7) & 0x9D2C5680U;
+ y ^= (y << 15) & 0xEFC60000U;
+ y ^= (y >> 18);
+ return y;
}
///////////////////////// network ///////////////////////
@@ -77,9 +77,9 @@ uint randomMT()
template<class T>
static inline void putint_(T &p, int n)
{
- if(n<128 && n>-127) p.put(n);
- else if(n<0x8000 && n>=-0x8000) { p.put(0x80); p.put(n); p.put(n>>8); }
- else { p.put(0x81); p.put(n); p.put(n>>8); p.put(n>>16); p.put(n>>24); }
+ if(n<128 && n>-127) p.put(n);
+ else if(n<0x8000 && n>=-0x8000) { p.put(0x80); p.put(n); p.put(n>>8); }
+ else { p.put(0x81); p.put(n); p.put(n>>8); p.put(n>>16); p.put(n>>24); }
}
void putint(ucharbuf &p, int n) { putint_(p, n); }
void putint(packetbuf &p, int n) { putint_(p, n); }
@@ -87,35 +87,35 @@ void putint(vector<uchar> &p, int n) { putint_(p, n); }
int getint(ucharbuf &p)
{
- int c = (schar)p.get();
- if(c==-128) { int n = p.get(); n |= ((schar)p.get())<<8; return n; }
- else if(c==-127) { int n = p.get(); n |= p.get()<<8; n |= p.get()<<16; return n|(p.get()<<24); }
- else return c;
+ int c = (schar)p.get();
+ if(c==-128) { int n = p.get(); n |= ((schar)p.get())<<8; return n; }
+ else if(c==-127) { int n = p.get(); n |= p.get()<<8; n |= p.get()<<16; return n|(p.get()<<24); }
+ else return c;
}
// much smaller encoding for unsigned integers up to 28 bits, but can handle signed
template<class T>
static inline void putuint_(T &p, int n)
{
- if(n < 0 || n >= (1<<21))
- {
- p.put(0x80 | (n & 0x7F));
- p.put(0x80 | ((n >> 7) & 0x7F));
- p.put(0x80 | ((n >> 14) & 0x7F));
- p.put(n >> 21);
- }
- else if(n < (1<<7)) p.put(n);
- else if(n < (1<<14))
- {
- p.put(0x80 | (n & 0x7F));
- p.put(n >> 7);
- }
- else
- {
- p.put(0x80 | (n & 0x7F));
- p.put(0x80 | ((n >> 7) & 0x7F));
- p.put(n >> 14);
- }
+ if(n < 0 || n >= (1<<21))
+ {
+ p.put(0x80 | (n & 0x7F));
+ p.put(0x80 | ((n >> 7) & 0x7F));
+ p.put(0x80 | ((n >> 14) & 0x7F));
+ p.put(n >> 21);
+ }
+ else if(n < (1<<7)) p.put(n);
+ else if(n < (1<<14))
+ {
+ p.put(0x80 | (n & 0x7F));
+ p.put(n >> 7);
+ }
+ else
+ {
+ p.put(0x80 | (n & 0x7F));
+ p.put(0x80 | ((n >> 7) & 0x7F));
+ p.put(n >> 14);
+ }
}
void putuint(ucharbuf &p, int n) { putuint_(p, n); }
void putuint(packetbuf &p, int n) { putuint_(p, n); }
@@ -123,22 +123,22 @@ void putuint(vector<uchar> &p, int n) { putuint_(p, n); }
int getuint(ucharbuf &p)
{
- int n = p.get();
- if(n & 0x80)
- {
- n += (p.get() << 7) - 0x80;
- if(n & (1<<14)) n += (p.get() << 14) - (1<<14);
- if(n & (1<<21)) n += (p.get() << 21) - (1<<21);
- if(n & (1<<28)) n |= ~0U<<28;
- }
- return n;
+ int n = p.get();
+ if(n & 0x80)
+ {
+ n += (p.get() << 7) - 0x80;
+ if(n & (1<<14)) n += (p.get() << 14) - (1<<14);
+ if(n & (1<<21)) n += (p.get() << 21) - (1<<21);
+ if(n & (1<<28)) n |= ~0U<<28;
+ }
+ return n;
}
template<class T>
static inline void putfloat_(T &p, float f)
{
- lilswap(&f, 1);
- p.put((uchar *)&f, sizeof(float));
+ lilswap(&f, 1);
+ p.put((uchar *)&f, sizeof(float));
}
void putfloat(ucharbuf &p, float f) { putfloat_(p, f); }
void putfloat(packetbuf &p, float f) { putfloat_(p, f); }
@@ -146,16 +146,16 @@ void putfloat(vector<uchar> &p, float f) { putfloat_(p, f); }
float getfloat(ucharbuf &p)
{
- float f;
- p.get((uchar *)&f, sizeof(float));
- return lilswap(f);
+ float f;
+ p.get((uchar *)&f, sizeof(float));
+ return lilswap(f);
}
template<class T>
static inline void sendstring_(const char *t, T &p)
{
- while(*t) putint(p, *t++);
- putint(p, 0);
+ while(*t) putint(p, *t++);
+ putint(p, 0);
}
void sendstring(const char *t, ucharbuf &p) { sendstring_(t, p); }
void sendstring(const char *t, packetbuf &p) { sendstring_(t, p); }
@@ -163,84 +163,84 @@ void sendstring(const char *t, vector<uchar> &p) { sendstring_(t, p); }
void getstring(char *text, ucharbuf &p, size_t len)
{
- char *t = text;
- do
- {
- if(t>=&text[len]) { text[len-1] = 0; return; }
- if(!p.remaining()) { *t = 0; return; }
- *t = getint(p);
- }
- while(*t++);
+ char *t = text;
+ do
+ {
+ if(t>=&text[len]) { text[len-1] = 0; return; }
+ if(!p.remaining()) { *t = 0; return; }
+ *t = getint(p);
+ }
+ while(*t++);
}
void filtertext(char *dst, const char *src, bool whitespace, bool forcespace, size_t len)
{
- for(int c = uchar(*src); c; c = uchar(*++src))
- {
- if(c == '\f')
- {
- if(!*++src) break;
- continue;
- }
- if(!iscubeprint(c))
- {
- if(!iscubespace(c) || !whitespace) continue;
- if(forcespace) c = ' ';
- }
- *dst++ = c;
- if(!--len) break;
- }
- *dst = '\0';
+ for(int c = uchar(*src); c; c = uchar(*++src))
+ {
+ if(c == '\f')
+ {
+ if(!*++src) break;
+ continue;
+ }
+ if(!iscubeprint(c))
+ {
+ if(!iscubespace(c) || !whitespace) continue;
+ if(forcespace) c = ' ';
+ }
+ *dst++ = c;
+ if(!--len) break;
+ }
+ *dst = '\0';
}
void ipmask::parse(const char *name)
{
- union { uchar b[sizeof(enet_uint32)]; enet_uint32 i; } ipconv, maskconv;
- ipconv.i = 0;
- maskconv.i = 0;
- loopi(4)
- {
- char *end = NULL;
- int n = strtol(name, &end, 10);
- if(!end) break;
- if(end > name) { ipconv.b[i] = n; maskconv.b[i] = 0xFF; }
- name = end;
- while(int c = *name)
- {
- ++name;
- if(c == '.') break;
- if(c == '/')
- {
- int range = clamp(int(strtol(name, NULL, 10)), 0, 32);
- mask = range ? ENET_HOST_TO_NET_32(0xFFffFFff << (32 - range)) : maskconv.i;
- ip = ipconv.i & mask;
- return;
- }
- }
- }
- ip = ipconv.i;
- mask = maskconv.i;
+ union { uchar b[sizeof(enet_uint32)]; enet_uint32 i; } ipconv, maskconv;
+ ipconv.i = 0;
+ maskconv.i = 0;
+ loopi(4)
+ {
+ char *end = NULL;
+ int n = strtol(name, &end, 10);
+ if(!end) break;
+ if(end > name) { ipconv.b[i] = n; maskconv.b[i] = 0xFF; }
+ name = end;
+ while(int c = *name)
+ {
+ ++name;
+ if(c == '.') break;
+ if(c == '/')
+ {
+ int range = clamp(int(strtol(name, NULL, 10)), 0, 32);
+ mask = range ? ENET_HOST_TO_NET_32(0xFFffFFff << (32 - range)) : maskconv.i;
+ ip = ipconv.i & mask;
+ return;
+ }
+ }
+ }
+ ip = ipconv.i;
+ mask = maskconv.i;
}
int ipmask::print(char *buf) const
{
- char *start = buf;
- union { uchar b[sizeof(enet_uint32)]; enet_uint32 i; } ipconv, maskconv;
- ipconv.i = ip;
- maskconv.i = mask;
- int lastdigit = -1;
- loopi(4) if(maskconv.b[i])
- {
- if(lastdigit >= 0) *buf++ = '.';
- loopj(i - lastdigit - 1) { *buf++ = '*'; *buf++ = '.'; }
- buf += sprintf(buf, "%d", ipconv.b[i]);
- lastdigit = i;
- }
- enet_uint32 bits = ~ENET_NET_TO_HOST_32(mask);
- int range = 32;
- for(; (bits&0xFF) == 0xFF; bits >>= 8) range -= 8;
- for(; bits&1; bits >>= 1) --range;
- if(!bits && range%8) buf += sprintf(buf, "/%d", range);
- return int(buf-start);
+ char *start = buf;
+ union { uchar b[sizeof(enet_uint32)]; enet_uint32 i; } ipconv, maskconv;
+ ipconv.i = ip;
+ maskconv.i = mask;
+ int lastdigit = -1;
+ loopi(4) if(maskconv.b[i])
+ {
+ if(lastdigit >= 0) *buf++ = '.';
+ loopj(i - lastdigit - 1) { *buf++ = '*'; *buf++ = '.'; }
+ buf += sprintf(buf, "%d", ipconv.b[i]);
+ lastdigit = i;
+ }
+ enet_uint32 bits = ~ENET_NET_TO_HOST_32(mask);
+ int range = 32;
+ for(; (bits&0xFF) == 0xFF; bits >>= 8) range -= 8;
+ for(; bits&1; bits >>= 1) --range;
+ if(!bits && range%8) buf += sprintf(buf, "/%d", range);
+ return int(buf-start);
}
diff --git a/src/shared/tools.h b/src/shared/tools.h
index c66f5bd..0550668 100644
--- a/src/shared/tools.h
+++ b/src/shared/tools.h
@@ -16,23 +16,9 @@ typedef unsigned long ulong;
typedef signed long long int llong;
typedef unsigned long long int ullong;
-#ifdef _DEBUG
-#define ASSERT(c) assert(c)
-#else
#define ASSERT(c) if(c) {}
-#endif
-
-#if defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1400)
#define RESTRICT __restrict
-#else
-#define RESTRICT
-#endif
-
-#ifdef __GNUC__
#define UNUSED __attribute__((unused))
-#else
-#define UNUSED
-#endif
void *operator new(size_t, bool);
void *operator new[](size_t, bool);
@@ -47,9 +33,9 @@ inline void operator delete[](void *, void *) {}
template<class T>
static inline void swap(T &a, T &b)
{
- T t = a;
- a = b;
- b = t;
+ T t = a;
+ a = b;
+ b = t;
}
#ifdef max
#undef max
@@ -60,42 +46,20 @@ static inline void swap(T &a, T &b)
template<class T>
static inline T max(T a, T b)
{
- return a > b ? a : b;
+ return a > b ? a : b;
}
template<class T>
static inline T min(T a, T b)
{
- return a < b ? a : b;
+ return a < b ? a : b;
}
template<class T, class U>
static inline T clamp(T a, U b, U c)
{
- return max(T(b), min(a, T(c)));
+ return max(T(b), min(a, T(c)));
}
-#ifdef __GNUC__
#define bitscan(mask) (__builtin_ffs(mask)-1)
-#else
-#ifdef WIN32
-#pragma intrinsic(_BitScanForward)
-static inline int bitscan(uint mask)
-{
- ulong i;
- return _BitScanForward(&i, mask) ? i : -1;
-}
-#else
-static inline int bitscan(uint mask)
-{
- if(!mask) return -1;
- int i = 1;
- if(!(mask&0xFFFF)) { i += 16; mask >>= 16; }
- if(!(mask&0xFF)) { i += 8; mask >>= 8; }
- if(!(mask&0xF)) { i += 4; mask >>= 4; }
- if(!(mask&3)) { i += 2; mask >>= 2; }
- return i - (mask&1);
-}
-#endif
-#endif
#define rnd(x) ((int)(randomMT()&0x7FFFFFFF)%(x))
#define rndscale(x) (float((randomMT()&0x7FFFFFFF)*double(x)/double(0x7FFFFFFF)))
@@ -121,37 +85,11 @@ static inline int bitscan(uint mask)
#define SQRT3 (1.7320508f)
#define RAD (PI / 180.0f)
-#ifdef WIN32
-#ifndef M_PI
-#define M_PI 3.14159265358979323846
-#endif
-#ifndef M_LN2
-#define M_LN2 0.693147180559945309417
-#endif
-
-#ifndef __GNUC__
-#pragma warning (3: 4189) // local variable is initialized but not referenced
-#pragma warning (disable: 4244) // conversion from 'int' to 'float', possible loss of data
-#pragma warning (disable: 4267) // conversion from 'size_t' to 'int', possible loss of data
-#pragma warning (disable: 4355) // 'this' : used in base member initializer list
-#pragma warning (disable: 4996) // 'strncpy' was declared deprecated
-#endif
-
-#define strcasecmp _stricmp
-#define strncasecmp _strnicmp
-#define PATHDIV '\\'
-
-#else
#define __cdecl
#define _vsnprintf vsnprintf
#define PATHDIV '/'
-#endif
-#ifdef __GNUC__
#define PRINTFARGS(fmt, args) __attribute__((format(printf, fmt, args)))
-#else
-#define PRINTFARGS(fmt, args)
-#endif
// easy safe strings
@@ -163,10 +101,10 @@ template<size_t N> inline void vformatstring(char (&d)[N], const char *fmt, va_l
inline char *copystring(char *d, const char *s, size_t len)
{
- size_t slen = min(strlen(s), len-1);
- memcpy(d, s, slen);
- d[slen] = 0;
- return d;
+ size_t slen = min(strlen(s), len-1);
+ memcpy(d, s, slen);
+ d[slen] = 0;
+ return d;
}
template<size_t N> inline char *copystring(char (&d)[N], const char *s) { return copystring(d, s, N); }
@@ -175,40 +113,40 @@ template<size_t N> inline char *concatstring(char (&d)[N], const char *s) { retu
inline char *prependstring(char *d, const char *s, size_t len)
{
- size_t slen = min(strlen(s), len);
- memmove(&d[slen], d, min(len - slen, strlen(d) + 1));
- memcpy(d, s, slen);
- d[len-1] = 0;
- return d;
+ size_t slen = min(strlen(s), len);
+ memmove(&d[slen], d, min(len - slen, strlen(d) + 1));
+ memcpy(d, s, slen);
+ d[len-1] = 0;
+ return d;
}
template<size_t N> inline char *prependstring(char (&d)[N], const char *s) { return prependstring(d, s, N); }
inline void nformatstring(char *d, int len, const char *fmt, ...) PRINTFARGS(3, 4);
inline void nformatstring(char *d, int len, const char *fmt, ...)
{
- va_list v;
- va_start(v, fmt);
- vformatstring(d, fmt, v, len);
- va_end(v);
+ va_list v;
+ va_start(v, fmt);
+ vformatstring(d, fmt, v, len);
+ va_end(v);
}
template<size_t N> inline void formatstring(char (&d)[N], const char *fmt, ...) PRINTFARGS(2, 3);
template<size_t N> inline void formatstring(char (&d)[N], const char *fmt, ...)
{
- va_list v;
- va_start(v, fmt);
- vformatstring(d, fmt, v, int(N));
- va_end(v);
+ va_list v;
+ va_start(v, fmt);
+ vformatstring(d, fmt, v, int(N));
+ va_end(v);
}
template<size_t N> inline void concformatstring(char (&d)[N], const char *fmt, ...) PRINTFARGS(2, 3);
template<size_t N> inline void concformatstring(char (&d)[N], const char *fmt, ...)
{
- va_list v;
- va_start(v, fmt);
- int len = strlen(d);
- vformatstring(d + len, fmt, v, int(N) - len);
- va_end(v);
+ va_list v;
+ va_start(v, fmt);
+ int len = strlen(d);
+ vformatstring(d + len, fmt, v, int(N) - len);
+ va_end(v);
}
#define defformatstring(d,...) string d; formatstring(d, __VA_ARGS__)
@@ -216,14 +154,14 @@ template<size_t N> inline void concformatstring(char (&d)[N], const char *fmt, .
template<size_t N> inline bool matchstring(const char *s, size_t len, const char (&d)[N])
{
- return len == N-1 && !memcmp(s, d, N-1);
+ return len == N-1 && !memcmp(s, d, N-1);
}
-inline char *newstring(size_t l) { return new char[l+1]; }
+inline char *newstring(size_t l) { return new char[l+1]; }
inline char *newstring(const char *s, size_t l) { return copystring(newstring(l), s, l+1); }
-inline char *newstring(const char *s) { size_t l = strlen(s); char *d = newstring(l); memcpy(d, s, l+1); return d; }
+inline char *newstring(const char *s) { size_t l = strlen(s); char *d = newstring(l); memcpy(d, s, l+1); return d; }
-#define loopv(v) for(int i = 0; i<(v).length(); i++)
+#define loopv(v) for(int i = 0; i<(v).length(); i++)
#define loopvj(v) for(int j = 0; j<(v).length(); j++)
#define loopvk(v) for(int k = 0; k<(v).length(); k++)
#define loopvrev(v) for(int i = (v).length()-1; i>=0; i--)
@@ -235,100 +173,100 @@ template<class T, size_t N> inline void memclear(T (&p)[N]) { memset((void *)p,
template <class T>
struct databuf
{
- enum
- {
- OVERREAD = 1<<0,
- OVERWROTE = 1<<1
- };
-
- T *buf;
- int len, maxlen;
- uchar flags;
-
- databuf() : buf(NULL), len(0), maxlen(0), flags(0) {}
-
- template<class U>
- databuf(T *buf, U maxlen) : buf(buf), len(0), maxlen((int)maxlen), flags(0) {}
-
- void reset()
- {
- len = 0;
- flags = 0;
- }
-
- void reset(T *buf_, int maxlen_)
- {
- reset();
- buf = buf_;
- maxlen = maxlen_;
- }
-
- const T &get()
- {
- static T overreadval = 0;
- if(len<maxlen) return buf[len++];
- flags |= OVERREAD;
- return overreadval;
- }
-
- databuf subbuf(int sz)
- {
- sz = clamp(sz, 0, maxlen-len);
- len += sz;
- return databuf(&buf[len-sz], sz);
- }
-
- T *pad(int numvals)
- {
- T *vals = &buf[len];
- len += min(numvals, maxlen-len);
- return vals;
- }
-
- void put(const T &val)
- {
- if(len<maxlen) buf[len++] = val;
- else flags |= OVERWROTE;
- }
-
- void put(const T *vals, int numvals)
- {
- if(maxlen-len<numvals) flags |= OVERWROTE;
- memcpy(&buf[len], (const void *)vals, min(maxlen-len, numvals)*sizeof(T));
- len += min(maxlen-len, numvals);
- }
-
- int get(T *vals, int numvals)
- {
- int read = min(maxlen-len, numvals);
- if(read<numvals) flags |= OVERREAD;
- memcpy(vals, (void *)&buf[len], read*sizeof(T));
- len += read;
- return read;
- }
-
- void offset(int n)
- {
- n = min(n, maxlen);
- buf += n;
- maxlen -= n;
- len = max(len-n, 0);
- }
-
- T *getbuf() const { return buf; }
- bool empty() const { return len==0; }
- int length() const { return len; }
- int remaining() const { return maxlen-len; }
- bool overread() const { return (flags&OVERREAD)!=0; }
- bool overwrote() const { return (flags&OVERWROTE)!=0; }
-
- bool check(int n) { return remaining() >= n; }
-
- void forceoverread()
- {
- len = maxlen;
- flags |= OVERREAD;
- }
+ enum
+ {
+ OVERREAD = 1<<0,
+ OVERWROTE = 1<<1
+ };
+
+ T *buf;
+ int len, maxlen;
+ uchar flags;
+
+ databuf() : buf(NULL), len(0), maxlen(0), flags(0) {}
+
+ template<class U>
+ databuf(T *buf, U maxlen) : buf(buf), len(0), maxlen((int)maxlen), flags(0) {}
+
+ void reset()
+ {
+ len = 0;
+ flags = 0;
+ }
+
+ void reset(T *buf_, int maxlen_)
+ {
+ reset();
+ buf = buf_;
+ maxlen = maxlen_;
+ }
+
+ const T &get()
+ {
+ static T overreadval = 0;
+ if(len<maxlen) return buf[len++];
+ flags |= OVERREAD;
+ return overreadval;
+ }
+
+ databuf subbuf(int sz)
+ {
+ sz = clamp(sz, 0, maxlen-len);
+ len += sz;
+ return databuf(&buf[len-sz], sz);
+ }
+
+ T *pad(int numvals)
+ {
+ T *vals = &buf[len];
+ len += min(numvals, maxlen-len);
+ return vals;
+ }
+
+ void put(const T &val)
+ {
+ if(len<maxlen) buf[len++] = val;
+ else flags |= OVERWROTE;
+ }
+
+ void put(const T *vals, int numvals)
+ {
+ if(maxlen-len<numvals) flags |= OVERWROTE;
+ memcpy(&buf[len], (const void *)vals, min(maxlen-len, numvals)*sizeof(T));
+ len += min(maxlen-len, numvals);
+ }
+
+ int get(T *vals, int numvals)
+ {
+ int read = min(maxlen-len, numvals);
+ if(read<numvals) flags |= OVERREAD;
+ memcpy(vals, (void *)&buf[len], read*sizeof(T));
+ len += read;
+ return read;
+ }
+
+ void offset(int n)
+ {
+ n = min(n, maxlen);
+ buf += n;
+ maxlen -= n;
+ len = max(len-n, 0);
+ }
+
+ T *getbuf() const { return buf; }
+ bool empty() const { return len==0; }
+ int length() const { return len; }
+ int remaining() const { return maxlen-len; }
+ bool overread() const { return (flags&OVERREAD)!=0; }
+ bool overwrote() const { return (flags&OVERWROTE)!=0; }
+
+ bool check(int n) { return remaining() >= n; }
+
+ void forceoverread()
+ {
+ len = maxlen;
+ flags |= OVERREAD;
+ }
};
typedef databuf<char> charbuf;
@@ -336,60 +274,60 @@ typedef databuf<uchar> ucharbuf;
struct packetbuf : ucharbuf
{
- ENetPacket *packet;
- int growth;
-
- packetbuf(ENetPacket *packet) : ucharbuf(packet->data, packet->dataLength), packet(packet), growth(0) {}
- packetbuf(int growth, int pflags = 0) : growth(growth)
- {
- packet = enet_packet_create(NULL, growth, pflags);
- buf = (uchar *)packet->data;
- maxlen = packet->dataLength;
- }
- ~packetbuf() { cleanup(); }
-
- void reliable() { packet->flags |= ENET_PACKET_FLAG_RELIABLE; }
-
- void resize(int n)
- {
- enet_packet_resize(packet, n);
- buf = (uchar *)packet->data;
- maxlen = packet->dataLength;
- }
-
- void checkspace(int n)
- {
- if(len + n > maxlen && packet && growth > 0) resize(max(len + n, maxlen + growth));
- }
-
- ucharbuf subbuf(int sz)
- {
- checkspace(sz);
- return ucharbuf::subbuf(sz);
- }
-
- void put(const uchar &val)
- {
- checkspace(1);
- ucharbuf::put(val);
- }
-
- void put(const uchar *vals, int numvals)
- {
- checkspace(numvals);
- ucharbuf::put(vals, numvals);
- }
-
- ENetPacket *finalize()
- {
- resize(len);
- return packet;
- }
-
- void cleanup()
- {
- if(growth > 0 && packet && !packet->referenceCount) { enet_packet_destroy(packet); packet = NULL; buf = NULL; len = maxlen = 0; }
- }
+ ENetPacket *packet;
+ int growth;
+
+ packetbuf(ENetPacket *packet) : ucharbuf(packet->data, packet->dataLength), packet(packet), growth(0) {}
+ packetbuf(int growth, int pflags = 0) : growth(growth)
+ {
+ packet = enet_packet_create(NULL, growth, pflags);
+ buf = (uchar *)packet->data;
+ maxlen = packet->dataLength;
+ }
+ ~packetbuf() { cleanup(); }
+
+ void reliable() { packet->flags |= ENET_PACKET_FLAG_RELIABLE; }
+
+ void resize(int n)
+ {
+ enet_packet_resize(packet, n);
+ buf = (uchar *)packet->data;
+ maxlen = packet->dataLength;
+ }
+
+ void checkspace(int n)
+ {
+ if(len + n > maxlen && packet && growth > 0) resize(max(len + n, maxlen + growth));
+ }
+
+ ucharbuf subbuf(int sz)
+ {
+ checkspace(sz);
+ return ucharbuf::subbuf(sz);
+ }
+
+ void put(const uchar &val)
+ {
+ checkspace(1);
+ ucharbuf::put(val);
+ }
+
+ void put(const uchar *vals, int numvals)
+ {
+ checkspace(numvals);
+ ucharbuf::put(vals, numvals);
+ }
+
+ ENetPacket *finalize()
+ {
+ resize(len);
+ return packet;
+ }
+
+ void cleanup()
+ {
+ if(growth > 0 && packet && !packet->referenceCount) { enet_packet_destroy(packet); packet = NULL; buf = NULL; len = maxlen = 0; }
+ }
};
template<class T>
@@ -397,130 +335,130 @@ static inline float heapscore(const T &n) { return n; }
struct sortless
{
- template<class T> bool operator()(const T &x, const T &y) const { return x < y; }
- bool operator()(char *x, char *y) const { return strcmp(x, y) < 0; }
- bool operator()(const char *x, const char *y) const { return strcmp(x, y) < 0; }
+ template<class T> bool operator()(const T &x, const T &y) const { return x < y; }
+ bool operator()(char *x, char *y) const { return strcmp(x, y) < 0; }
+ bool operator()(const char *x, const char *y) const { return strcmp(x, y) < 0; }
};
struct sortnameless
{
- template<class T> bool operator()(const T &x, const T &y) const { return sortless()(x.name, y.name); }
- template<class T> bool operator()(T *x, T *y) const { return sortless()(x->name, y->name); }
- template<class T> bool operator()(const T *x, const T *y) const { return sortless()(x->name, y->name); }
+ template<class T> bool operator()(const T &x, const T &y) const { return sortless()(x.name, y.name); }
+ template<class T> bool operator()(T *x, T *y) const { return sortless()(x->name, y->name); }
+ template<class T> bool operator()(const T *x, const T *y) const { return sortless()(x->name, y->name); }
};
template<class T, class F>
static inline void insertionsort(T *start, T *end, F fun)
{
- for(T *i = start+1; i < end; i++)
- {
- if(fun(*i, i[-1]))
- {
- T tmp = *i;
- *i = i[-1];
- T *j = i-1;
- for(; j > start && fun(tmp, j[-1]); --j)
- *j = j[-1];
- *j = tmp;
- }
- }
+ for(T *i = start+1; i < end; i++)
+ {
+ if(fun(*i, i[-1]))
+ {
+ T tmp = *i;
+ *i = i[-1];
+ T *j = i-1;
+ for(; j > start && fun(tmp, j[-1]); --j)
+ *j = j[-1];
+ *j = tmp;
+ }
+ }
}
template<class T, class F>
static inline void insertionsort(T *buf, int n, F fun)
{
- insertionsort(buf, buf+n, fun);
+ insertionsort(buf, buf+n, fun);
}
template<class T>
static inline void insertionsort(T *buf, int n)
{
- insertionsort(buf, buf+n, sortless());
+ insertionsort(buf, buf+n, sortless());
}
template<class T, class F>
static inline void quicksort(T *start, T *end, F fun)
{
- while(end-start > 10)
- {
- T *mid = &start[(end-start)/2], *i = start+1, *j = end-2, pivot;
- if(fun(*start, *mid)) /* start < mid */
- {
- if(fun(end[-1], *start)) { pivot = *start; *start = end[-1]; end[-1] = *mid; } /* end < start < mid */
- else if(fun(end[-1], *mid)) { pivot = end[-1]; end[-1] = *mid; } /* start <= end < mid */
- else { pivot = *mid; } /* start < mid <= end */
- }
- else if(fun(*start, end[-1])) { pivot = *start; *start = *mid; } /*mid <= start < end */
- else if(fun(*mid, end[-1])) { pivot = end[-1]; end[-1] = *start; *start = *mid; } /* mid < end <= start */
- else { pivot = *mid; swap(*start, end[-1]); } /* end <= mid <= start */
- *mid = end[-2];
- do
- {
- while(fun(*i, pivot)) if(++i >= j) goto partitioned;
- while(fun(pivot, *--j)) if(i >= j) goto partitioned;
- swap(*i, *j);
- }
- while(++i < j);
- partitioned:
- end[-2] = *i;
- *i = pivot;
-
- if(i-start < end-(i+1))
- {
- quicksort(start, i, fun);
- start = i+1;
- }
- else
- {
- quicksort(i+1, end, fun);
- end = i;
- }
- }
-
- insertionsort(start, end, fun);
+ while(end-start > 10)
+ {
+ T *mid = &start[(end-start)/2], *i = start+1, *j = end-2, pivot;
+ if(fun(*start, *mid)) /* start < mid */
+ {
+ if(fun(end[-1], *start)) { pivot = *start; *start = end[-1]; end[-1] = *mid; } /* end < start < mid */
+ else if(fun(end[-1], *mid)) { pivot = end[-1]; end[-1] = *mid; } /* start <= end < mid */
+ else { pivot = *mid; } /* start < mid <= end */
+ }
+ else if(fun(*start, end[-1])) { pivot = *start; *start = *mid; } /*mid <= start < end */
+ else if(fun(*mid, end[-1])) { pivot = end[-1]; end[-1] = *start; *start = *mid; } /* mid < end <= start */
+ else { pivot = *mid; swap(*start, end[-1]); } /* end <= mid <= start */
+ *mid = end[-2];
+ do
+ {
+ while(fun(*i, pivot)) if(++i >= j) goto partitioned;
+ while(fun(pivot, *--j)) if(i >= j) goto partitioned;
+ swap(*i, *j);
+ }
+ while(++i < j);
+ partitioned:
+ end[-2] = *i;
+ *i = pivot;
+
+ if(i-start < end-(i+1))
+ {
+ quicksort(start, i, fun);
+ start = i+1;
+ }
+ else
+ {
+ quicksort(i+1, end, fun);
+ end = i;
+ }
+ }
+
+ insertionsort(start, end, fun);
}
template<class T, class F>
static inline void quicksort(T *buf, int n, F fun)
{
- quicksort(buf, buf+n, fun);
+ quicksort(buf, buf+n, fun);
}
template<class T>
static inline void quicksort(T *buf, int n)
{
- quicksort(buf, buf+n, sortless());
+ quicksort(buf, buf+n, sortless());
}
template<class T> struct isclass
{
- template<class C> static char test(void (C::*)(void));
- template<class C> static int test(...);
- enum { yes = sizeof(test<T>(0)) == 1 ? 1 : 0, no = yes^1 };
+ template<class C> static char test(void (C::*)(void));
+ template<class C> static int test(...);
+ enum { yes = sizeof(test<T>(0)) == 1 ? 1 : 0, no = yes^1 };
};
static inline uint hthash(const char *key)
{
- uint h = 5381;
- for(int i = 0, k; (k = key[i]); i++) h = ((h<<5)+h)^k; // bernstein k=33 xor
- return h;
+ uint h = 5381;
+ for(int i = 0, k; (k = key[i]); i++) h = ((h<<5)+h)^k; // bernstein k=33 xor
+ return h;
}
static inline bool htcmp(const char *x, const char *y)
{
- return !strcmp(x, y);
+ return !strcmp(x, y);
}
struct stringslice
{
- const char *str;
- int len;
- stringslice() {}
- stringslice(const char *str, int len) : str(str), len(len) {}
- stringslice(const char *str, const char *end) : str(str), len(int(end-str)) {}
+ const char *str;
+ int len;
+ stringslice() {}
+ stringslice(const char *str, int len) : str(str), len(len) {}
+ stringslice(const char *str, const char *end) : str(str), len(int(end-str)) {}
- const char *end() const { return &str[len]; }
+ const char *end() const { return &str[len]; }
};
inline char *newstring(const stringslice &s) { return newstring(s.str, s.len); }
@@ -531,668 +469,668 @@ inline int stringlen(const stringslice &s) { return s.len; }
inline char *copystring(char *d, const stringslice &s, size_t len)
{
- size_t slen = min(size_t(s.len), len-1);
- memcpy(d, s.str, slen);
- d[slen] = 0;
- return d;
+ size_t slen = min(size_t(s.len), len-1);
+ memcpy(d, s.str, slen);
+ d[slen] = 0;
+ return d;
}
template<size_t N> inline char *copystring(char (&d)[N], const stringslice &s) { return copystring(d, s, N); }
static inline uint memhash(const void *ptr, int len)
{
- const uchar *data = (const uchar *)ptr;
- uint h = 5381;
- loopi(len) h = ((h<<5)+h)^data[i];
- return h;
+ const uchar *data = (const uchar *)ptr;
+ uint h = 5381;
+ loopi(len) h = ((h<<5)+h)^data[i];
+ return h;
}
static inline uint hthash(const stringslice &s) { return memhash(s.str, s.len); }
static inline bool htcmp(const stringslice &x, const char *y)
{
- return x.len == (int)strlen(y) && !memcmp(x.str, y, x.len);
+ return x.len == (int)strlen(y) && !memcmp(x.str, y, x.len);
}
static inline uint hthash(int key)
{
- return key;
+ return key;
}
static inline bool htcmp(int x, int y)
{
- return x==y;
+ return x==y;
}
#ifndef STANDALONE
static inline uint hthash(GLuint key)
{
- return key;
+ return key;
}
static inline bool htcmp(GLuint x, GLuint y)
{
- return x==y;
+ return x==y;
}
#endif
template <class T> struct vector
{
- static const int MINSIZE = 8;
-
- T *buf;
- int alen, ulen;
-
- vector() : buf(NULL), alen(0), ulen(0)
- {
- }
-
- vector(const vector &v) : buf(NULL), alen(0), ulen(0)
- {
- *this = v;
- }
-
- ~vector() { shrink(0); if(buf) delete[] (uchar *)buf; }
-
- vector<T> &operator=(const vector<T> &v)
- {
- shrink(0);
- if(v.length() > alen) growbuf(v.length());
- loopv(v) add(v[i]);
- return *this;
- }
-
- T &add(const T &x)
- {
- if(ulen==alen) growbuf(ulen+1);
- new (&buf[ulen]) T(x);
- return buf[ulen++];
- }
-
- T &add()
- {
- if(ulen==alen) growbuf(ulen+1);
- new (&buf[ulen]) T;
- return buf[ulen++];
- }
-
- T &dup()
- {
- if(ulen==alen) growbuf(ulen+1);
- new (&buf[ulen]) T(buf[ulen-1]);
- return buf[ulen++];
- }
-
- void move(vector<T> &v)
- {
- if(!ulen)
- {
- swap(buf, v.buf);
- swap(ulen, v.ulen);
- swap(alen, v.alen);
- }
- else
- {
- growbuf(ulen+v.ulen);
- if(v.ulen) memcpy(&buf[ulen], (void *)v.buf, v.ulen*sizeof(T));
- ulen += v.ulen;
- v.ulen = 0;
- }
- }
-
- bool inrange(size_t i) const { return i<size_t(ulen); }
- bool inrange(int i) const { return i>=0 && i<ulen; }
-
- T &pop() { return buf[--ulen]; }
- T &last() { return buf[ulen-1]; }
- void drop() { ulen--; buf[ulen].~T(); }
- bool empty() const { return ulen==0; }
-
- int capacity() const { return alen; }
- int length() const { return ulen; }
- T &operator[](int i) { ASSERT(i>=0 && i<ulen); return buf[i]; }
- const T &operator[](int i) const { ASSERT(i >= 0 && i<ulen); return buf[i]; }
-
- void disown() { buf = NULL; alen = ulen = 0; }
-
- void shrink(int i) { ASSERT(i<=ulen); if(isclass<T>::no) ulen = i; else while(ulen>i) drop(); }
- void setsize(int i) { ASSERT(i<=ulen); ulen = i; }
-
- void deletecontents() { while(!empty()) delete pop(); }
- void deletearrays() { while(!empty()) delete[] pop(); }
-
- T *getbuf() { return buf; }
- const T *getbuf() const { return buf; }
- bool inbuf(const T *e) const { return e >= buf && e < &buf[ulen]; }
-
- template<class F>
- void sort(F fun, int i = 0, int n = -1)
- {
- quicksort(&buf[i], n < 0 ? ulen-i : n, fun);
- }
-
- void sort() { sort(sortless()); }
- void sortname() { sort(sortnameless()); }
-
- void growbuf(int sz)
- {
- int olen = alen;
- if(alen <= 0) alen = max(MINSIZE, sz);
- else while(alen < sz) alen += alen/2;
- if(alen <= olen) return;
- uchar *newbuf = new uchar[alen*sizeof(T)];
- if(olen > 0)
- {
- if(ulen > 0) memcpy(newbuf, (void *)buf, ulen*sizeof(T));
- delete[] (uchar *)buf;
- }
- buf = (T *)newbuf;
- }
-
- databuf<T> reserve(int sz)
- {
- if(alen-ulen < sz) growbuf(ulen+sz);
- return databuf<T>(&buf[ulen], sz);
- }
-
- void advance(int sz)
- {
- ulen += sz;
- }
-
- void addbuf(const databuf<T> &p)
- {
- advance(p.length());
- }
-
- T *pad(int n)
- {
- T *buf = reserve(n).buf;
- advance(n);
- return buf;
- }
-
- void put(const T &v) { add(v); }
-
- void put(const T *v, int n)
- {
- databuf<T> buf = reserve(n);
- buf.put(v, n);
- addbuf(buf);
- }
-
- void remove(int i, int n)
- {
- for(int p = i+n; p<ulen; p++) buf[p-n] = buf[p];
- ulen -= n;
- }
-
- T remove(int i)
- {
- T e = buf[i];
- for(int p = i+1; p<ulen; p++) buf[p-1] = buf[p];
- ulen--;
- return e;
- }
-
- T removeunordered(int i)
- {
- T e = buf[i];
- ulen--;
- if(ulen>0) buf[i] = buf[ulen];
- return e;
- }
-
- template<class U>
- int find(const U &o)
- {
- loopi(ulen) if(buf[i]==o) return i;
- return -1;
- }
-
- void addunique(const T &o)
- {
- if(find(o) < 0) add(o);
- }
-
- void removeobj(const T &o)
- {
- loopi(ulen) if(buf[i] == o)
- {
- int dst = i;
- for(int j = i+1; j < ulen; j++) if(!(buf[j] == o)) buf[dst++] = buf[j];
- setsize(dst);
- break;
- }
- }
-
- void replacewithlast(const T &o)
- {
- if(!ulen) return;
- loopi(ulen-1) if(buf[i]==o)
- {
- buf[i] = buf[ulen-1];
- break;
- }
- ulen--;
- }
-
- T &insert(int i, const T &e)
- {
- add(T());
- for(int p = ulen-1; p>i; p--) buf[p] = buf[p-1];
- buf[i] = e;
- return buf[i];
- }
-
- T *insert(int i, const T *e, int n)
- {
- if(alen-ulen < n) growbuf(ulen+n);
- loopj(n) add(T());
- for(int p = ulen-1; p>=i+n; p--) buf[p] = buf[p-n];
- loopj(n) buf[i+j] = e[j];
- return &buf[i];
- }
-
- void reverse()
- {
- loopi(ulen/2) swap(buf[i], buf[ulen-1-i]);
- }
-
- static int heapparent(int i) { return (i - 1) >> 1; }
- static int heapchild(int i) { return (i << 1) + 1; }
-
- void buildheap()
- {
- for(int i = ulen/2; i >= 0; i--) downheap(i);
- }
-
- int upheap(int i)
- {
- float score = heapscore(buf[i]);
- while(i > 0)
- {
- int pi = heapparent(i);
- if(score >= heapscore(buf[pi])) break;
- swap(buf[i], buf[pi]);
- i = pi;
- }
- return i;
- }
-
- T &addheap(const T &x)
- {
- add(x);
- return buf[upheap(ulen-1)];
- }
-
- int downheap(int i)
- {
- float score = heapscore(buf[i]);
- for(;;)
- {
- int ci = heapchild(i);
- if(ci >= ulen) break;
- float cscore = heapscore(buf[ci]);
- if(score > cscore)
- {
- if(ci+1 < ulen && heapscore(buf[ci+1]) < cscore) { swap(buf[ci+1], buf[i]); i = ci+1; }
- else { swap(buf[ci], buf[i]); i = ci; }
- }
- else if(ci+1 < ulen && heapscore(buf[ci+1]) < score) { swap(buf[ci+1], buf[i]); i = ci+1; }
- else break;
- }
- return i;
- }
-
- T removeheap()
- {
- T e = removeunordered(0);
- if(ulen) downheap(0);
- return e;
- }
-
- template<class K>
- int htfind(const K &key)
- {
- loopi(ulen) if(htcmp(key, buf[i])) return i;
- return -1;
- }
+ static const int MINSIZE = 8;
+
+ T *buf;
+ int alen, ulen;
+
+ vector() : buf(NULL), alen(0), ulen(0)
+ {
+ }
+
+ vector(const vector &v) : buf(NULL), alen(0), ulen(0)
+ {
+ *this = v;
+ }
+
+ ~vector() { shrink(0); if(buf) delete[] (uchar *)buf; }
+
+ vector<T> &operator=(const vector<T> &v)
+ {
+ shrink(0);
+ if(v.length() > alen) growbuf(v.length());
+ loopv(v) add(v[i]);
+ return *this;
+ }
+
+ T &add(const T &x)
+ {
+ if(ulen==alen) growbuf(ulen+1);
+ new (&buf[ulen]) T(x);
+ return buf[ulen++];
+ }
+
+ T &add()
+ {
+ if(ulen==alen) growbuf(ulen+1);
+ new (&buf[ulen]) T;
+ return buf[ulen++];
+ }
+
+ T &dup()
+ {
+ if(ulen==alen) growbuf(ulen+1);
+ new (&buf[ulen]) T(buf[ulen-1]);
+ return buf[ulen++];
+ }
+
+ void move(vector<T> &v)
+ {
+ if(!ulen)
+ {
+ swap(buf, v.buf);
+ swap(ulen, v.ulen);
+ swap(alen, v.alen);
+ }
+ else
+ {
+ growbuf(ulen+v.ulen);
+ if(v.ulen) memcpy(&buf[ulen], (void *)v.buf, v.ulen*sizeof(T));
+ ulen += v.ulen;
+ v.ulen = 0;
+ }
+ }
+
+ bool inrange(size_t i) const { return i<size_t(ulen); }
+ bool inrange(int i) const { return i>=0 && i<ulen; }
+
+ T &pop() { return buf[--ulen]; }
+ T &last() { return buf[ulen-1]; }
+ void drop() { ulen--; buf[ulen].~T(); }
+ bool empty() const { return ulen==0; }
+
+ int capacity() const { return alen; }
+ int length() const { return ulen; }
+ T &operator[](int i) { ASSERT(i>=0 && i<ulen); return buf[i]; }
+ const T &operator[](int i) const { ASSERT(i >= 0 && i<ulen); return buf[i]; }
+
+ void disown() { buf = NULL; alen = ulen = 0; }
+
+ void shrink(int i) { ASSERT(i<=ulen); if(isclass<T>::no) ulen = i; else while(ulen>i) drop(); }
+ void setsize(int i) { ASSERT(i<=ulen); ulen = i; }
+
+ void deletecontents() { while(!empty()) delete pop(); }
+ void deletearrays() { while(!empty()) delete[] pop(); }
+
+ T *getbuf() { return buf; }
+ const T *getbuf() const { return buf; }
+ bool inbuf(const T *e) const { return e >= buf && e < &buf[ulen]; }
+
+ template<class F>
+ void sort(F fun, int i = 0, int n = -1)
+ {
+ quicksort(&buf[i], n < 0 ? ulen-i : n, fun);
+ }
+
+ void sort() { sort(sortless()); }
+ void sortname() { sort(sortnameless()); }
+
+ void growbuf(int sz)
+ {
+ int olen = alen;
+ if(alen <= 0) alen = max(MINSIZE, sz);
+ else while(alen < sz) alen += alen/2;
+ if(alen <= olen) return;
+ uchar *newbuf = new uchar[alen*sizeof(T)];
+ if(olen > 0)
+ {
+ if(ulen > 0) memcpy(newbuf, (void *)buf, ulen*sizeof(T));
+ delete[] (uchar *)buf;
+ }
+ buf = (T *)newbuf;
+ }
+
+ databuf<T> reserve(int sz)
+ {
+ if(alen-ulen < sz) growbuf(ulen+sz);
+ return databuf<T>(&buf[ulen], sz);
+ }
+
+ void advance(int sz)
+ {
+ ulen += sz;
+ }
+
+ void addbuf(const databuf<T> &p)
+ {
+ advance(p.length());
+ }
+
+ T *pad(int n)
+ {
+ T *buf = reserve(n).buf;
+ advance(n);
+ return buf;
+ }
+
+ void put(const T &v) { add(v); }
+
+ void put(const T *v, int n)
+ {
+ databuf<T> buf = reserve(n);
+ buf.put(v, n);
+ addbuf(buf);
+ }
+
+ void remove(int i, int n)
+ {
+ for(int p = i+n; p<ulen; p++) buf[p-n] = buf[p];
+ ulen -= n;
+ }
+
+ T remove(int i)
+ {
+ T e = buf[i];
+ for(int p = i+1; p<ulen; p++) buf[p-1] = buf[p];
+ ulen--;
+ return e;
+ }
+
+ T removeunordered(int i)
+ {
+ T e = buf[i];
+ ulen--;
+ if(ulen>0) buf[i] = buf[ulen];
+ return e;
+ }
+
+ template<class U>
+ int find(const U &o)
+ {
+ loopi(ulen) if(buf[i]==o) return i;
+ return -1;
+ }
+
+ void addunique(const T &o)
+ {
+ if(find(o) < 0) add(o);
+ }
+
+ void removeobj(const T &o)
+ {
+ loopi(ulen) if(buf[i] == o)
+ {
+ int dst = i;
+ for(int j = i+1; j < ulen; j++) if(!(buf[j] == o)) buf[dst++] = buf[j];
+ setsize(dst);
+ break;
+ }
+ }
+
+ void replacewithlast(const T &o)
+ {
+ if(!ulen) return;
+ loopi(ulen-1) if(buf[i]==o)
+ {
+ buf[i] = buf[ulen-1];
+ break;
+ }
+ ulen--;
+ }
+
+ T &insert(int i, const T &e)
+ {
+ add(T());
+ for(int p = ulen-1; p>i; p--) buf[p] = buf[p-1];
+ buf[i] = e;
+ return buf[i];
+ }
+
+ T *insert(int i, const T *e, int n)
+ {
+ if(alen-ulen < n) growbuf(ulen+n);
+ loopj(n) add(T());
+ for(int p = ulen-1; p>=i+n; p--) buf[p] = buf[p-n];
+ loopj(n) buf[i+j] = e[j];
+ return &buf[i];
+ }
+
+ void reverse()
+ {
+ loopi(ulen/2) swap(buf[i], buf[ulen-1-i]);
+ }
+
+ static int heapparent(int i) { return (i - 1) >> 1; }
+ static int heapchild(int i) { return (i << 1) + 1; }
+
+ void buildheap()
+ {
+ for(int i = ulen/2; i >= 0; i--) downheap(i);
+ }
+
+ int upheap(int i)
+ {
+ float score = heapscore(buf[i]);
+ while(i > 0)
+ {
+ int pi = heapparent(i);
+ if(score >= heapscore(buf[pi])) break;
+ swap(buf[i], buf[pi]);
+ i = pi;
+ }
+ return i;
+ }
+
+ T &addheap(const T &x)
+ {
+ add(x);
+ return buf[upheap(ulen-1)];
+ }
+
+ int downheap(int i)
+ {
+ float score = heapscore(buf[i]);
+ for(;;)
+ {
+ int ci = heapchild(i);
+ if(ci >= ulen) break;
+ float cscore = heapscore(buf[ci]);
+ if(score > cscore)
+ {
+ if(ci+1 < ulen && heapscore(buf[ci+1]) < cscore) { swap(buf[ci+1], buf[i]); i = ci+1; }
+ else { swap(buf[ci], buf[i]); i = ci; }
+ }
+ else if(ci+1 < ulen && heapscore(buf[ci+1]) < score) { swap(buf[ci+1], buf[i]); i = ci+1; }
+ else break;
+ }
+ return i;
+ }
+
+ T removeheap()
+ {
+ T e = removeunordered(0);
+ if(ulen) downheap(0);
+ return e;
+ }
+
+ template<class K>
+ int htfind(const K &key)
+ {
+ loopi(ulen) if(htcmp(key, buf[i])) return i;
+ return -1;
+ }
};
template<class H, class E, class K, class T> struct hashbase
{
- typedef E elemtype;
- typedef K keytype;
- typedef T datatype;
-
- enum { CHUNKSIZE = 64 };
-
- struct chain { E elem; chain *next; };
- struct chainchunk { chain chains[CHUNKSIZE]; chainchunk *next; };
-
- int size;
- int numelems;
- chain **chains;
-
- chainchunk *chunks;
- chain *unused;
-
- enum { DEFAULTSIZE = 1<<10 };
-
- hashbase(int size = DEFAULTSIZE)
- : size(size)
- {
- numelems = 0;
- chunks = NULL;
- unused = NULL;
- chains = new chain *[size];
- memset(chains, 0, size*sizeof(chain *));
- }
-
- ~hashbase()
- {
- DELETEA(chains);
- deletechunks();
- }
-
- chain *insert(uint h)
- {
- if(!unused)
- {
- chainchunk *chunk = new chainchunk;
- chunk->next = chunks;
- chunks = chunk;
- loopi(CHUNKSIZE-1) chunk->chains[i].next = &chunk->chains[i+1];
- chunk->chains[CHUNKSIZE-1].next = unused;
- unused = chunk->chains;
- }
- chain *c = unused;
- unused = unused->next;
- c->next = chains[h];
- chains[h] = c;
- numelems++;
- return c;
- }
-
- template<class U>
- T &insert(uint h, const U &key)
- {
- chain *c = insert(h);
- H::setkey(c->elem, key);
- return H::getdata(c->elem);
- }
-
- #define HTFIND(success, fail) \
- uint h = hthash(key)&(this->size-1); \
- for(chain *c = this->chains[h]; c; c = c->next) \
- { \
- if(htcmp(key, H::getkey(c->elem))) return success H::getdata(c->elem); \
- } \
- return (fail);
-
- template<class U>
- T *access(const U &key)
- {
- HTFIND(&, NULL);
- }
-
- template<class U, class V>
- T &access(const U &key, const V &elem)
- {
- HTFIND( , insert(h, key) = elem);
- }
-
- template<class U>
- T &operator[](const U &key)
- {
- HTFIND( , insert(h, key));
- }
-
- template<class U>
- T &find(const U &key, T &notfound)
- {
- HTFIND( , notfound);
- }
-
- template<class U>
- const T &find(const U &key, const T &notfound)
- {
- HTFIND( , notfound);
- }
-
- template<class U>
- bool remove(const U &key)
- {
- uint h = hthash(key)&(size-1);
- for(chain **p = &chains[h], *c = chains[h]; c; p = &c->next, c = c->next)
- {
- if(htcmp(key, H::getkey(c->elem)))
- {
- *p = c->next;
- c->elem.~E();
- new (&c->elem) E;
- c->next = unused;
- unused = c;
- numelems--;
- return true;
- }
- }
- return false;
- }
-
- void deletechunks()
- {
- for(chainchunk *nextchunk; chunks; chunks = nextchunk)
- {
- nextchunk = chunks->next;
- delete chunks;
- }
- }
-
- void clear()
- {
- if(!numelems) return;
- memset(chains, 0, size*sizeof(chain *));
- numelems = 0;
- unused = NULL;
- deletechunks();
- }
-
- static inline chain *enumnext(void *i) { return ((chain *)i)->next; }
- static inline K &enumkey(void *i) { return H::getkey(((chain *)i)->elem); }
- static inline T &enumdata(void *i) { return H::getdata(((chain *)i)->elem); }
+ typedef E elemtype;
+ typedef K keytype;
+ typedef T datatype;
+
+ enum { CHUNKSIZE = 64 };
+
+ struct chain { E elem; chain *next; };
+ struct chainchunk { chain chains[CHUNKSIZE]; chainchunk *next; };
+
+ int size;
+ int numelems;
+ chain **chains;
+
+ chainchunk *chunks;
+ chain *unused;
+
+ enum { DEFAULTSIZE = 1<<10 };
+
+ hashbase(int size = DEFAULTSIZE)
+ : size(size)
+ {
+ numelems = 0;
+ chunks = NULL;
+ unused = NULL;
+ chains = new chain *[size];
+ memset(chains, 0, size*sizeof(chain *));
+ }
+
+ ~hashbase()
+ {
+ DELETEA(chains);
+ deletechunks();
+ }
+
+ chain *insert(uint h)
+ {
+ if(!unused)
+ {
+ chainchunk *chunk = new chainchunk;
+ chunk->next = chunks;
+ chunks = chunk;
+ loopi(CHUNKSIZE-1) chunk->chains[i].next = &chunk->chains[i+1];
+ chunk->chains[CHUNKSIZE-1].next = unused;
+ unused = chunk->chains;
+ }
+ chain *c = unused;
+ unused = unused->next;
+ c->next = chains[h];
+ chains[h] = c;
+ numelems++;
+ return c;
+ }
+
+ template<class U>
+ T &insert(uint h, const U &key)
+ {
+ chain *c = insert(h);
+ H::setkey(c->elem, key);
+ return H::getdata(c->elem);
+ }
+
+ #define HTFIND(success, fail) \
+ uint h = hthash(key)&(this->size-1); \
+ for(chain *c = this->chains[h]; c; c = c->next) \
+ { \
+ if(htcmp(key, H::getkey(c->elem))) return success H::getdata(c->elem); \
+ } \
+ return (fail);
+
+ template<class U>
+ T *access(const U &key)
+ {
+ HTFIND(&, NULL);
+ }
+
+ template<class U, class V>
+ T &access(const U &key, const V &elem)
+ {
+ HTFIND( , insert(h, key) = elem);
+ }
+
+ template<class U>
+ T &operator[](const U &key)
+ {
+ HTFIND( , insert(h, key));
+ }
+
+ template<class U>
+ T &find(const U &key, T &notfound)
+ {
+ HTFIND( , notfound);
+ }
+
+ template<class U>
+ const T &find(const U &key, const T &notfound)
+ {
+ HTFIND( , notfound);
+ }
+
+ template<class U>
+ bool remove(const U &key)
+ {
+ uint h = hthash(key)&(size-1);
+ for(chain **p = &chains[h], *c = chains[h]; c; p = &c->next, c = c->next)
+ {
+ if(htcmp(key, H::getkey(c->elem)))
+ {
+ *p = c->next;
+ c->elem.~E();
+ new (&c->elem) E;
+ c->next = unused;
+ unused = c;
+ numelems--;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ void deletechunks()
+ {
+ for(chainchunk *nextchunk; chunks; chunks = nextchunk)
+ {
+ nextchunk = chunks->next;
+ delete chunks;
+ }
+ }
+
+ void clear()
+ {
+ if(!numelems) return;
+ memset(chains, 0, size*sizeof(chain *));
+ numelems = 0;
+ unused = NULL;
+ deletechunks();
+ }
+
+ static inline chain *enumnext(void *i) { return ((chain *)i)->next; }
+ static inline K &enumkey(void *i) { return H::getkey(((chain *)i)->elem); }
+ static inline T &enumdata(void *i) { return H::getdata(((chain *)i)->elem); }
};
template<class T> struct hashset : hashbase<hashset<T>, T, T, T>
{
- typedef hashbase<hashset<T>, T, T, T> basetype;
+ typedef hashbase<hashset<T>, T, T, T> basetype;
- hashset(int size = basetype::DEFAULTSIZE) : basetype(size) {}
+ hashset(int size = basetype::DEFAULTSIZE) : basetype(size) {}
- static inline const T &getkey(const T &elem) { return elem; }
- static inline T &getdata(T &elem) { return elem; }
- template<class K> static inline void setkey(T &elem, const K &key) {}
+ static inline const T &getkey(const T &elem) { return elem; }
+ static inline T &getdata(T &elem) { return elem; }
+ template<class K> static inline void setkey(T &elem, const K &key) {}
- template<class V>
- T &add(const V &elem)
- {
- return basetype::access(elem, elem);
- }
+ template<class V>
+ T &add(const V &elem)
+ {
+ return basetype::access(elem, elem);
+ }
};
template<class T> struct hashnameset : hashbase<hashnameset<T>, T, const char *, T>
{
- typedef hashbase<hashnameset<T>, T, const char *, T> basetype;
+ typedef hashbase<hashnameset<T>, T, const char *, T> basetype;
- hashnameset(int size = basetype::DEFAULTSIZE) : basetype(size) {}
+ hashnameset(int size = basetype::DEFAULTSIZE) : basetype(size) {}
- template<class U> static inline const char *getkey(const U &elem) { return elem.name; }
- template<class U> static inline const char *getkey(U *elem) { return elem->name; }
- static inline T &getdata(T &elem) { return elem; }
- template<class K> static inline void setkey(T &elem, const K &key) {}
+ template<class U> static inline const char *getkey(const U &elem) { return elem.name; }
+ template<class U> static inline const char *getkey(U *elem) { return elem->name; }
+ static inline T &getdata(T &elem) { return elem; }
+ template<class K> static inline void setkey(T &elem, const K &key) {}
- template<class V>
- T &add(const V &elem)
- {
- return basetype::access(getkey(elem), elem);
- }
+ template<class V>
+ T &add(const V &elem)
+ {
+ return basetype::access(getkey(elem), elem);
+ }
};
template<class K, class T> struct hashtableentry
{
- K key;
- T data;
+ K key;
+ T data;
};
template<class K, class T> struct hashtable : hashbase<hashtable<K, T>, hashtableentry<K, T>, K, T>
{
- typedef hashbase<hashtable<K, T>, hashtableentry<K, T>, K, T> basetype;
- typedef typename basetype::elemtype elemtype;
+ typedef hashbase<hashtable<K, T>, hashtableentry<K, T>, K, T> basetype;
+ typedef typename basetype::elemtype elemtype;
- hashtable(int size = basetype::DEFAULTSIZE) : basetype(size) {}
+ hashtable(int size = basetype::DEFAULTSIZE) : basetype(size) {}
- static inline K &getkey(elemtype &elem) { return elem.key; }
- static inline T &getdata(elemtype &elem) { return elem.data; }
- template<class U> static inline void setkey(elemtype &elem, const U &key) { elem.key = key; }
+ static inline K &getkey(elemtype &elem) { return elem.key; }
+ static inline T &getdata(elemtype &elem) { return elem.data; }
+ template<class U> static inline void setkey(elemtype &elem, const U &key) { elem.key = key; }
};
#define enumeratekt(ht,k,e,t,f,b) loopi((ht).size) for(void *ec = (ht).chains[i]; ec;) { k &e = (ht).enumkey(ec); t &f = (ht).enumdata(ec); ec = (ht).enumnext(ec); b; }
-#define enumerate(ht,t,e,b) loopi((ht).size) for(void *ec = (ht).chains[i]; ec;) { t &e = (ht).enumdata(ec); ec = (ht).enumnext(ec); b; }
+#define enumerate(ht,t,e,b) loopi((ht).size) for(void *ec = (ht).chains[i]; ec;) { t &e = (ht).enumdata(ec); ec = (ht).enumnext(ec); b; }
struct unionfind
{
- struct ufval
- {
- int rank, next;
-
- ufval() : rank(0), next(-1) {}
- };
-
- vector<ufval> ufvals;
-
- int find(int k)
- {
- if(k>=ufvals.length()) return k;
- while(ufvals[k].next>=0) k = ufvals[k].next;
- return k;
- }
-
- int compressfind(int k)
- {
- if(ufvals[k].next<0) return k;
- return ufvals[k].next = compressfind(ufvals[k].next);
- }
-
- void unite (int x, int y)
- {
- while(ufvals.length() <= max(x, y)) ufvals.add();
- x = compressfind(x);
- y = compressfind(y);
- if(x==y) return;
- ufval &xval = ufvals[x], &yval = ufvals[y];
- if(xval.rank < yval.rank) xval.next = y;
- else
- {
- yval.next = x;
- if(xval.rank==yval.rank) yval.rank++;
- }
- }
+ struct ufval
+ {
+ int rank, next;
+
+ ufval() : rank(0), next(-1) {}
+ };
+
+ vector<ufval> ufvals;
+
+ int find(int k)
+ {
+ if(k>=ufvals.length()) return k;
+ while(ufvals[k].next>=0) k = ufvals[k].next;
+ return k;
+ }
+
+ int compressfind(int k)
+ {
+ if(ufvals[k].next<0) return k;
+ return ufvals[k].next = compressfind(ufvals[k].next);
+ }
+
+ void unite (int x, int y)
+ {
+ while(ufvals.length() <= max(x, y)) ufvals.add();
+ x = compressfind(x);
+ y = compressfind(y);
+ if(x==y) return;
+ ufval &xval = ufvals[x], &yval = ufvals[y];
+ if(xval.rank < yval.rank) xval.next = y;
+ else
+ {
+ yval.next = x;
+ if(xval.rank==yval.rank) yval.rank++;
+ }
+ }
};
template <class T, int SIZE> struct queue
{
- int head, tail, len;
- T data[SIZE];
-
- queue() { clear(); }
-
- void clear() { head = tail = len = 0; }
-
- int capacity() const { return SIZE; }
- int length() const { return len; }
- bool empty() const { return !len; }
- bool full() const { return len == SIZE; }
-
- bool inrange(size_t i) const { return i<size_t(len); }
- bool inrange(int i) const { return i>=0 && i<len; }
-
- T &added() { return data[tail > 0 ? tail-1 : SIZE-1]; }
- T &added(int offset) { return data[tail-offset > 0 ? tail-offset-1 : tail-offset-1 + SIZE]; }
- T &adding() { return data[tail]; }
- T &adding(int offset) { return data[tail+offset >= SIZE ? tail+offset - SIZE : tail+offset]; }
- T &add()
- {
- T &t = data[tail];
- tail++;
- if(tail >= SIZE) tail -= SIZE;
- if(len < SIZE) len++;
- return t;
- }
- T &add(const T &e) { return add() = e; }
-
- databuf<T> reserve(int sz)
- {
- if(!len) head = tail = 0;
- return databuf<T>(&data[tail], min(sz, SIZE-tail));
- }
-
- void advance(int sz)
- {
- if(len + sz > SIZE) sz = SIZE - len;
- tail += sz;
- if(tail >= SIZE) tail -= SIZE;
- len += sz;
- }
-
- void addbuf(const databuf<T> &p)
- {
- advance(p.length());
- }
-
- T &pop()
- {
- tail--;
- if(tail < 0) tail += SIZE;
- len--;
- return data[tail];
- }
-
- T &removing() { return data[head]; }
- T &removing(int offset) { return data[head+offset >= SIZE ? head+offset - SIZE : head+offset]; }
- T &remove()
- {
- T &t = data[head];
- head++;
- if(head >= SIZE) head -= SIZE;
- len--;
- return t;
- }
-
- T remove(int offset)
- {
- T val = removing(offset);
- if(head+offset >= SIZE) for(int i = head+offset - SIZE + 1; i < tail; i++) data[i-1] = data[i];
- else if(head < tail) for(int i = head+offset + 1; i < tail; i++) data[i-1] = data[i];
- else
- {
- for(int i = head+offset + 1; i < SIZE; i++) data[i-1] = data[i];
- data[SIZE-1] = data[0];
- for(int i = 1; i < tail; i++) data[i-1] = data[i];
- }
- tail--;
- if(tail < 0) tail += SIZE;
- len--;
- return val;
- }
-
- T &operator[](int offset) { return removing(offset); }
- const T &operator[](int offset) const { return removing(offset); }
+ int head, tail, len;
+ T data[SIZE];
+
+ queue() { clear(); }
+
+ void clear() { head = tail = len = 0; }
+
+ int capacity() const { return SIZE; }
+ int length() const { return len; }
+ bool empty() const { return !len; }
+ bool full() const { return len == SIZE; }
+
+ bool inrange(size_t i) const { return i<size_t(len); }
+ bool inrange(int i) const { return i>=0 && i<len; }
+
+ T &added() { return data[tail > 0 ? tail-1 : SIZE-1]; }
+ T &added(int offset) { return data[tail-offset > 0 ? tail-offset-1 : tail-offset-1 + SIZE]; }
+ T &adding() { return data[tail]; }
+ T &adding(int offset) { return data[tail+offset >= SIZE ? tail+offset - SIZE : tail+offset]; }
+ T &add()
+ {
+ T &t = data[tail];
+ tail++;
+ if(tail >= SIZE) tail -= SIZE;
+ if(len < SIZE) len++;
+ return t;
+ }
+ T &add(const T &e) { return add() = e; }
+
+ databuf<T> reserve(int sz)
+ {
+ if(!len) head = tail = 0;
+ return databuf<T>(&data[tail], min(sz, SIZE-tail));
+ }
+
+ void advance(int sz)
+ {
+ if(len + sz > SIZE) sz = SIZE - len;
+ tail += sz;
+ if(tail >= SIZE) tail -= SIZE;
+ len += sz;
+ }
+
+ void addbuf(const databuf<T> &p)
+ {
+ advance(p.length());
+ }
+
+ T &pop()
+ {
+ tail--;
+ if(tail < 0) tail += SIZE;
+ len--;
+ return data[tail];
+ }
+
+ T &removing() { return data[head]; }
+ T &removing(int offset) { return data[head+offset >= SIZE ? head+offset - SIZE : head+offset]; }
+ T &remove()
+ {
+ T &t = data[head];
+ head++;
+ if(head >= SIZE) head -= SIZE;
+ len--;
+ return t;
+ }
+
+ T remove(int offset)
+ {
+ T val = removing(offset);
+ if(head+offset >= SIZE) for(int i = head+offset - SIZE + 1; i < tail; i++) data[i-1] = data[i];
+ else if(head < tail) for(int i = head+offset + 1; i < tail; i++) data[i-1] = data[i];
+ else
+ {
+ for(int i = head+offset + 1; i < SIZE; i++) data[i-1] = data[i];
+ data[SIZE-1] = data[0];
+ for(int i = 1; i < tail; i++) data[i-1] = data[i];
+ }
+ tail--;
+ if(tail < 0) tail += SIZE;
+ len--;
+ return val;
+ }
+
+ T &operator[](int offset) { return removing(offset); }
+ const T &operator[](int offset) const { return removing(offset); }
};
template <class T, int SIZE> struct reversequeue : queue<T, SIZE>
{
- T &operator[](int offset) { return queue<T, SIZE>::added(offset); }
- const T &operator[](int offset) const { return queue<T, SIZE>::added(offset); }
+ T &operator[](int offset) { return queue<T, SIZE>::added(offset); }
+ const T &operator[](int offset) const { return queue<T, SIZE>::added(offset); }
};
const int islittleendian = 1;
@@ -1239,83 +1177,67 @@ template<class T> inline T bigswap(T n) { return *(const uchar *)&islittleendian
template<class T> inline void bigswap(T *buf, size_t len) { if(*(const uchar *)&islittleendian) endianswap(buf, len); }
#endif
-/* workaround for some C platforms that have these two functions as macros - not used anywhere */
-#ifdef getchar
-#undef getchar
-#endif
-#ifdef putchar
-#undef putchar
-#endif
-
struct stream
{
-#ifdef WIN32
-#if defined(__GNUC__) && !defined(__MINGW32__)
- typedef off64_t offset;
-#else
- typedef __int64 offset;
-#endif
-#else
- typedef off_t offset;
-#endif
-
- virtual ~stream() {}
- virtual void close() = 0;
- virtual bool end() = 0;
- virtual offset tell() { return -1; }
- virtual offset rawtell() { return tell(); }
- virtual bool seek(offset pos, int whence = SEEK_SET) { return false; }
- virtual offset size();
- virtual offset rawsize() { return size(); }
- virtual size_t read(void *buf, size_t len) { return 0; }
- virtual size_t write(const void *buf, size_t len) { return 0; }
- virtual bool flush() { return true; }
- virtual int getchar() { uchar c; return read(&c, 1) == 1 ? c : -1; }
- virtual bool putchar(int n) { uchar c = n; return write(&c, 1) == 1; }
- virtual bool getline(char *str, size_t len);
- virtual bool putstring(const char *str) { size_t len = strlen(str); return write(str, len) == len; }
- virtual bool putline(const char *str) { return putstring(str) && putchar('\n'); }
- virtual size_t printf(const char *fmt, ...) PRINTFARGS(2, 3);
- virtual uint getcrc() { return 0; }
-
- template<class T> size_t put(const T *v, size_t n) { return write(v, n*sizeof(T))/sizeof(T); }
- template<class T> bool put(T n) { return write(&n, sizeof(n)) == sizeof(n); }
- template<class T> bool putlil(T n) { return put<T>(lilswap(n)); }
- template<class T> bool putbig(T n) { return put<T>(bigswap(n)); }
-
- template<class T> size_t get(T *v, size_t n) { return read(v, n*sizeof(T))/sizeof(T); }
- template<class T> T get() { T n; return read(&n, sizeof(n)) == sizeof(n) ? n : 0; }
- template<class T> T getlil() { return lilswap(get<T>()); }
- template<class T> T getbig() { return bigswap(get<T>()); }
+ typedef off_t offset;
+
+ virtual ~stream() {}
+ virtual void close() = 0;
+ virtual bool end() = 0;
+ virtual offset tell() { return -1; }
+ virtual offset rawtell() { return tell(); }
+ virtual bool seek(offset pos, int whence = SEEK_SET) { return false; }
+ virtual offset size();
+ virtual offset rawsize() { return size(); }
+ virtual size_t read(void *buf, size_t len) { return 0; }
+ virtual size_t write(const void *buf, size_t len) { return 0; }
+ virtual bool flush() { return true; }
+ virtual int getchar() { uchar c; return read(&c, 1) == 1 ? c : -1; }
+ virtual bool putchar(int n) { uchar c = n; return write(&c, 1) == 1; }
+ virtual bool getline(char *str, size_t len);
+ virtual bool putstring(const char *str) { size_t len = strlen(str); return write(str, len) == len; }
+ virtual bool putline(const char *str) { return putstring(str) && putchar('\n'); }
+ virtual size_t printf(const char *fmt, ...) PRINTFARGS(2, 3);
+ virtual uint getcrc() { return 0; }
+
+ template<class T> size_t put(const T *v, size_t n) { return write(v, n*sizeof(T))/sizeof(T); }
+ template<class T> bool put(T n) { return write(&n, sizeof(n)) == sizeof(n); }
+ template<class T> bool putlil(T n) { return put<T>(lilswap(n)); }
+ template<class T> bool putbig(T n) { return put<T>(bigswap(n)); }
+
+ template<class T> size_t get(T *v, size_t n) { return read(v, n*sizeof(T))/sizeof(T); }
+ template<class T> T get() { T n; return read(&n, sizeof(n)) == sizeof(n) ? n : 0; }
+ template<class T> T getlil() { return lilswap(get<T>()); }
+ template<class T> T getbig() { return bigswap(get<T>()); }
#ifndef STANDALONE
- SDL_RWops *rwops();
+ SDL_RWops *rwops();
#endif
};
template<class T>
struct streambuf
{
- stream *s;
-
- streambuf(stream *s) : s(s) {}
-
- T get() { return s->get<T>(); }
- size_t get(T *vals, size_t numvals) { return s->get(vals, numvals); }
- void put(const T &val) { s->put(&val, 1); }
- void put(const T *vals, size_t numvals) { s->put(vals, numvals); }
- size_t length() { return s->size(); }
+ stream *s;
+
+ streambuf(stream *s) : s(s) {}
+
+ T get() { return s->get<T>(); }
+ size_t get(T *vals, size_t numvals) { return s->get(vals, numvals); }
+ void put(const T &val) { s->put(&val, 1); }
+ void put(const T *vals, size_t numvals) { s->put(vals, numvals); }
+ size_t length() { return s->size(); }
};
enum
{
- CT_PRINT = 1<<0,
- CT_SPACE = 1<<1,
- CT_DIGIT = 1<<2,
- CT_ALPHA = 1<<3,
- CT_LOWER = 1<<4,
- CT_UPPER = 1<<5,
- CT_UNICODE = 1<<6
+ CT_PRINT = 1<<0,
+ CT_SPACE = 1<<1,
+ CT_DIGIT = 1<<2,
+ CT_ALPHA = 1<<3,
+ CT_LOWER = 1<<4,
+ CT_UPPER = 1<<5,
+ CT_UNICODE = 1<<6
};
extern const uchar cubectype[256];
static inline int iscubeprint(uchar c) { return cubectype[c]&CT_PRINT; }
@@ -1326,25 +1248,25 @@ static inline int iscubelower(uchar c) { return cubectype[c]&CT_LOWER; }
static inline int iscubeupper(uchar c) { return cubectype[c]&CT_UPPER; }
static inline int iscubepunct(uchar c) { return cubectype[c] == CT_PRINT; }
static inline int cube2uni(uchar c)
-{
- extern const int cube2unichars[256];
- return cube2unichars[c];
+{
+ extern const int cube2unichars[256];
+ return cube2unichars[c];
}
static inline uchar uni2cube(int c)
{
- extern const int uni2cubeoffsets[8];
- extern const uchar uni2cubechars[];
- return uint(c) <= 0x7FF ? uni2cubechars[uni2cubeoffsets[c>>8] + (c&0xFF)] : 0;
+ extern const int uni2cubeoffsets[8];
+ extern const uchar uni2cubechars[];
+ return uint(c) <= 0x7FF ? uni2cubechars[uni2cubeoffsets[c>>8] + (c&0xFF)] : 0;
}
static inline uchar cubelower(uchar c)
{
- extern const uchar cubelowerchars[256];
- return cubelowerchars[c];
+ extern const uchar cubelowerchars[256];
+ return cubelowerchars[c];
}
static inline uchar cubeupper(uchar c)
{
- extern const uchar cubeupperchars[256];
- return cubeupperchars[c];
+ extern const uchar cubeupperchars[256];
+ return cubeupperchars[c];
}
extern size_t decodeutf8(uchar *dst, size_t dstlen, const uchar *src, size_t srclen, size_t *carry = NULL);
extern size_t encodeutf8(uchar *dstbuf, size_t dstlen, const uchar *srcbuf, size_t srclen, size_t *carry = NULL);
@@ -1397,11 +1319,11 @@ template<size_t N> static inline void filtertext(char (&dst)[N], const char *src
struct ipmask
{
- enet_uint32 ip, mask;
+ enet_uint32 ip, mask;
- void parse(const char *name);
- int print(char *buf) const;
- bool check(enet_uint32 host) const { return (host & mask) == ip; }
+ void parse(const char *name);
+ int print(char *buf) const;
+ bool check(enet_uint32 host) const { return (host & mask) == ip; }
};
#endif
diff --git a/src/shared/zip.cpp b/src/shared/zip.cpp
index 40a3e9c..83b2952 100644
--- a/src/shared/zip.cpp
+++ b/src/shared/zip.cpp
@@ -2,583 +2,567 @@
enum
{
- ZIP_LOCAL_FILE_SIGNATURE = 0x04034B50,
- ZIP_LOCAL_FILE_SIZE = 30,
- ZIP_FILE_SIGNATURE = 0x02014B50,
- ZIP_FILE_SIZE = 46,
- ZIP_DIRECTORY_SIGNATURE = 0x06054B50,
- ZIP_DIRECTORY_SIZE = 22
+ ZIP_LOCAL_FILE_SIGNATURE = 0x04034B50,
+ ZIP_LOCAL_FILE_SIZE = 30,
+ ZIP_FILE_SIGNATURE = 0x02014B50,
+ ZIP_FILE_SIZE = 46,
+ ZIP_DIRECTORY_SIGNATURE = 0x06054B50,
+ ZIP_DIRECTORY_SIZE = 22
};
struct ziplocalfileheader
{
- uint signature;
- ushort version, flags, compression, modtime, moddate;
- uint crc32, compressedsize, uncompressedsize;
- ushort namelength, extralength;
+ uint signature;
+ ushort version, flags, compression, modtime, moddate;
+ uint crc32, compressedsize, uncompressedsize;
+ ushort namelength, extralength;
};
struct zipfileheader
{
- uint signature;
- ushort version, needversion, flags, compression, modtime, moddate;
- uint crc32, compressedsize, uncompressedsize;
- ushort namelength, extralength, commentlength, disknumber, internalattribs;
- uint externalattribs, offset;
+ uint signature;
+ ushort version, needversion, flags, compression, modtime, moddate;
+ uint crc32, compressedsize, uncompressedsize;
+ ushort namelength, extralength, commentlength, disknumber, internalattribs;
+ uint externalattribs, offset;
};
struct zipdirectoryheader
{
- uint signature;
- ushort disknumber, directorydisk, diskentries, entries;
- uint size, offset;
- ushort commentlength;
+ uint signature;
+ ushort disknumber, directorydisk, diskentries, entries;
+ uint size, offset;
+ ushort commentlength;
};
struct zipfile
{
- char *name;
- uint header, offset, size, compressedsize;
-
- zipfile() : name(NULL), header(0), offset(~0U), size(0), compressedsize(0)
- {
- }
- ~zipfile()
- {
- DELETEA(name);
- }
+ char *name;
+ uint header, offset, size, compressedsize;
+
+ zipfile() : name(NULL), header(0), offset(~0U), size(0), compressedsize(0)
+ {
+ }
+ ~zipfile()
+ {
+ DELETEA(name);
+ }
};
struct zipstream;
struct ziparchive
{
- char *name;
- FILE *data;
- hashnameset<zipfile> files;
- int openfiles;
- zipstream *owner;
-
- ziparchive() : name(NULL), data(NULL), files(512), openfiles(0), owner(NULL)
- {
- }
- ~ziparchive()
- {
- DELETEA(name);
- if(data) { fclose(data); data = NULL; }
- }
+ char *name;
+ FILE *data;
+ hashnameset<zipfile> files;
+ int openfiles;
+ zipstream *owner;
+
+ ziparchive() : name(NULL), data(NULL), files(512), openfiles(0), owner(NULL)
+ {
+ }
+ ~ziparchive()
+ {
+ DELETEA(name);
+ if(data) { fclose(data); data = NULL; }
+ }
};
static bool findzipdirectory(FILE *f, zipdirectoryheader &hdr)
{
- if(fseek(f, 0, SEEK_END) < 0) return false;
-
- long offset = ftell(f);
- if(offset < 0) return false;
-
- uchar buf[1024], *src = NULL;
- long end = max(offset - 0xFFFFL - ZIP_DIRECTORY_SIZE, 0L);
- size_t len = 0;
- const uint signature = lilswap<uint>(ZIP_DIRECTORY_SIGNATURE);
-
- while(offset > end)
- {
- size_t carry = min(len, size_t(ZIP_DIRECTORY_SIZE-1)), next = min(sizeof(buf) - carry, size_t(offset - end));
- offset -= next;
- memmove(&buf[next], buf, carry);
- if(next + carry < ZIP_DIRECTORY_SIZE || fseek(f, offset, SEEK_SET) < 0 || fread(buf, 1, next, f) != next) return false;
- len = next + carry;
- uchar *search = &buf[next-1];
- for(; search >= buf; search--) if(*(uint *)search == signature) break;
- if(search >= buf) { src = search; break; }
- }
-
- if(!src || &buf[len] - src < ZIP_DIRECTORY_SIZE) return false;
-
- hdr.signature = lilswap(*(uint *)src); src += 4;
- hdr.disknumber = lilswap(*(ushort *)src); src += 2;
- hdr.directorydisk = lilswap(*(ushort *)src); src += 2;
- hdr.diskentries = lilswap(*(ushort *)src); src += 2;
- hdr.entries = lilswap(*(ushort *)src); src += 2;
- hdr.size = lilswap(*(uint *)src); src += 4;
- hdr.offset = lilswap(*(uint *)src); src += 4;
- hdr.commentlength = lilswap(*(ushort *)src); src += 2;
-
- if(hdr.signature != ZIP_DIRECTORY_SIGNATURE || hdr.disknumber != hdr.directorydisk || hdr.diskentries != hdr.entries) return false;
-
- return true;
+ if(fseek(f, 0, SEEK_END) < 0) return false;
+
+ long offset = ftell(f);
+ if(offset < 0) return false;
+
+ uchar buf[1024], *src = NULL;
+ long end = max(offset - 0xFFFFL - ZIP_DIRECTORY_SIZE, 0L);
+ size_t len = 0;
+ const uint signature = lilswap<uint>(ZIP_DIRECTORY_SIGNATURE);
+
+ while(offset > end)
+ {
+ size_t carry = min(len, size_t(ZIP_DIRECTORY_SIZE-1)), next = min(sizeof(buf) - carry, size_t(offset - end));
+ offset -= next;
+ memmove(&buf[next], buf, carry);
+ if(next + carry < ZIP_DIRECTORY_SIZE || fseek(f, offset, SEEK_SET) < 0 || fread(buf, 1, next, f) != next) return false;
+ len = next + carry;
+ uchar *search = &buf[next-1];
+ for(; search >= buf; search--) if(*(uint *)search == signature) break;
+ if(search >= buf) { src = search; break; }
+ }
+
+ if(!src || &buf[len] - src < ZIP_DIRECTORY_SIZE) return false;
+
+ hdr.signature = lilswap(*(uint *)src); src += 4;
+ hdr.disknumber = lilswap(*(ushort *)src); src += 2;
+ hdr.directorydisk = lilswap(*(ushort *)src); src += 2;
+ hdr.diskentries = lilswap(*(ushort *)src); src += 2;
+ hdr.entries = lilswap(*(ushort *)src); src += 2;
+ hdr.size = lilswap(*(uint *)src); src += 4;
+ hdr.offset = lilswap(*(uint *)src); src += 4;
+ hdr.commentlength = lilswap(*(ushort *)src); src += 2;
+
+ if(hdr.signature != ZIP_DIRECTORY_SIGNATURE || hdr.disknumber != hdr.directorydisk || hdr.diskentries != hdr.entries) return false;
+
+ return true;
}
-#ifndef STANDALONE
-VAR(dbgzip, 0, 0, 1);
-#endif
-
static bool readzipdirectory(const char *archname, FILE *f, int entries, int offset, uint size, vector<zipfile> &files)
{
- uchar *buf = new (false) uchar[size], *src = buf;
- if(!buf || fseek(f, offset, SEEK_SET) < 0 || fread(buf, 1, size, f) != size) { delete[] buf; return false; }
- loopi(entries)
- {
- if(src + ZIP_FILE_SIZE > &buf[size]) break;
-
- zipfileheader hdr;
- hdr.signature = lilswap(*(uint *)src); src += 4;
- hdr.version = lilswap(*(ushort *)src); src += 2;
- hdr.needversion = lilswap(*(ushort *)src); src += 2;
- hdr.flags = lilswap(*(ushort *)src); src += 2;
- hdr.compression = lilswap(*(ushort *)src); src += 2;
- hdr.modtime = lilswap(*(ushort *)src); src += 2;
- hdr.moddate = lilswap(*(ushort *)src); src += 2;
- hdr.crc32 = lilswap(*(uint *)src); src += 4;
- hdr.compressedsize = lilswap(*(uint *)src); src += 4;
- hdr.uncompressedsize = lilswap(*(uint *)src); src += 4;
- hdr.namelength = lilswap(*(ushort *)src); src += 2;
- hdr.extralength = lilswap(*(ushort *)src); src += 2;
- hdr.commentlength = lilswap(*(ushort *)src); src += 2;
- hdr.disknumber = lilswap(*(ushort *)src); src += 2;
- hdr.internalattribs = lilswap(*(ushort *)src); src += 2;
- hdr.externalattribs = lilswap(*(uint *)src); src += 4;
- hdr.offset = lilswap(*(uint *)src); src += 4;
- if(hdr.signature != ZIP_FILE_SIGNATURE) break;
- if(!hdr.namelength || !hdr.uncompressedsize || (hdr.compression && (hdr.compression != Z_DEFLATED || !hdr.compressedsize)))
- {
- src += hdr.namelength + hdr.extralength + hdr.commentlength;
- continue;
- }
- if(src + hdr.namelength > &buf[size]) break;
-
- string pname;
- int namelen = min((int)hdr.namelength, (int)sizeof(pname)-1);
- memcpy(pname, src, namelen);
- pname[namelen] = '\0';
- path(pname);
- char *name = newstring(pname);
-
- zipfile &f = files.add();
- f.name = name;
- f.header = hdr.offset;
- f.size = hdr.uncompressedsize;
- f.compressedsize = hdr.compression ? hdr.compressedsize : 0;
-#ifndef STANDALONE
- if(dbgzip) conoutf(CON_DEBUG, "%s: file %s, size %d, compress %d, flags %x", archname, name, hdr.uncompressedsize, hdr.compression, hdr.flags);
-#endif
-
- src += hdr.namelength + hdr.extralength + hdr.commentlength;
- }
- delete[] buf;
-
- return files.length() > 0;
+ uchar *buf = new (false) uchar[size], *src = buf;
+ if(!buf || fseek(f, offset, SEEK_SET) < 0 || fread(buf, 1, size, f) != size) { delete[] buf; return false; }
+ loopi(entries)
+ {
+ if(src + ZIP_FILE_SIZE > &buf[size]) break;
+
+ zipfileheader hdr;
+ hdr.signature = lilswap(*(uint *)src); src += 4;
+ hdr.version = lilswap(*(ushort *)src); src += 2;
+ hdr.needversion = lilswap(*(ushort *)src); src += 2;
+ hdr.flags = lilswap(*(ushort *)src); src += 2;
+ hdr.compression = lilswap(*(ushort *)src); src += 2;
+ hdr.modtime = lilswap(*(ushort *)src); src += 2;
+ hdr.moddate = lilswap(*(ushort *)src); src += 2;
+ hdr.crc32 = lilswap(*(uint *)src); src += 4;
+ hdr.compressedsize = lilswap(*(uint *)src); src += 4;
+ hdr.uncompressedsize = lilswap(*(uint *)src); src += 4;
+ hdr.namelength = lilswap(*(ushort *)src); src += 2;
+ hdr.extralength = lilswap(*(ushort *)src); src += 2;
+ hdr.commentlength = lilswap(*(ushort *)src); src += 2;
+ hdr.disknumber = lilswap(*(ushort *)src); src += 2;
+ hdr.internalattribs = lilswap(*(ushort *)src); src += 2;
+ hdr.externalattribs = lilswap(*(uint *)src); src += 4;
+ hdr.offset = lilswap(*(uint *)src); src += 4;
+ if(hdr.signature != ZIP_FILE_SIGNATURE) break;
+ if(!hdr.namelength || !hdr.uncompressedsize || (hdr.compression && (hdr.compression != Z_DEFLATED || !hdr.compressedsize)))
+ {
+ src += hdr.namelength + hdr.extralength + hdr.commentlength;
+ continue;
+ }
+ if(src + hdr.namelength > &buf[size]) break;
+
+ string pname;
+ int namelen = min((int)hdr.namelength, (int)sizeof(pname)-1);
+ memcpy(pname, src, namelen);
+ pname[namelen] = '\0';
+ path(pname);
+ char *name = newstring(pname);
+
+ zipfile &f = files.add();
+ f.name = name;
+ f.header = hdr.offset;
+ f.size = hdr.uncompressedsize;
+ f.compressedsize = hdr.compression ? hdr.compressedsize : 0;
+
+ src += hdr.namelength + hdr.extralength + hdr.commentlength;
+ }
+ delete[] buf;
+
+ return files.length() > 0;
}
static bool readlocalfileheader(FILE *f, ziplocalfileheader &h, uint offset)
{
- uchar buf[ZIP_LOCAL_FILE_SIZE];
- if(fseek(f, offset, SEEK_SET) < 0 || fread(buf, 1, ZIP_LOCAL_FILE_SIZE, f) != ZIP_LOCAL_FILE_SIZE)
- return false;
- uchar *src = buf;
- h.signature = lilswap(*(uint *)src); src += 4;
- h.version = lilswap(*(ushort *)src); src += 2;
- h.flags = lilswap(*(ushort *)src); src += 2;
- h.compression = lilswap(*(ushort *)src); src += 2;
- h.modtime = lilswap(*(ushort *)src); src += 2;
- h.moddate = lilswap(*(ushort *)src); src += 2;
- h.crc32 = lilswap(*(uint *)src); src += 4;
- h.compressedsize = lilswap(*(uint *)src); src += 4;
- h.uncompressedsize = lilswap(*(uint *)src); src += 4;
- h.namelength = lilswap(*(ushort *)src); src += 2;
- h.extralength = lilswap(*(ushort *)src); src += 2;
- if(h.signature != ZIP_LOCAL_FILE_SIGNATURE) return false;
- // h.uncompressedsize or h.compressedsize may be zero - so don't validate
- return true;
+ uchar buf[ZIP_LOCAL_FILE_SIZE];
+ if(fseek(f, offset, SEEK_SET) < 0 || fread(buf, 1, ZIP_LOCAL_FILE_SIZE, f) != ZIP_LOCAL_FILE_SIZE)
+ return false;
+ uchar *src = buf;
+ h.signature = lilswap(*(uint *)src); src += 4;
+ h.version = lilswap(*(ushort *)src); src += 2;
+ h.flags = lilswap(*(ushort *)src); src += 2;
+ h.compression = lilswap(*(ushort *)src); src += 2;
+ h.modtime = lilswap(*(ushort *)src); src += 2;
+ h.moddate = lilswap(*(ushort *)src); src += 2;
+ h.crc32 = lilswap(*(uint *)src); src += 4;
+ h.compressedsize = lilswap(*(uint *)src); src += 4;
+ h.uncompressedsize = lilswap(*(uint *)src); src += 4;
+ h.namelength = lilswap(*(ushort *)src); src += 2;
+ h.extralength = lilswap(*(ushort *)src); src += 2;
+ if(h.signature != ZIP_LOCAL_FILE_SIGNATURE) return false;
+ // h.uncompressedsize or h.compressedsize may be zero - so don't validate
+ return true;
}
static vector<ziparchive *> archives;
ziparchive *findzip(const char *name)
{
- loopv(archives) if(!strcmp(name, archives[i]->name)) return archives[i];
- return NULL;
+ loopv(archives) if(!strcmp(name, archives[i]->name)) return archives[i];
+ return NULL;
}
static bool checkprefix(vector<zipfile> &files, const char *prefix, int prefixlen)
{
- loopv(files)
- {
- if(!strncmp(files[i].name, prefix, prefixlen)) return false;
- }
- return true;
+ loopv(files)
+ {
+ if(!strncmp(files[i].name, prefix, prefixlen)) return false;
+ }
+ return true;
}
static void mountzip(ziparchive &arch, vector<zipfile> &files, const char *mountdir, const char *stripdir)
{
- string packagesdir = "packages/";
- path(packagesdir);
- size_t striplen = stripdir ? strlen(stripdir) : 0;
- if(!mountdir && !stripdir) loopv(files)
- {
- zipfile &f = files[i];
- const char *foundpackages = strstr(f.name, packagesdir);
- if(foundpackages)
- {
- if(foundpackages > f.name)
- {
- stripdir = f.name;
- striplen = foundpackages - f.name;
- }
- break;
- }
- const char *foundogz = strstr(f.name, ".ogz");
- if(foundogz)
- {
- const char *ogzdir = foundogz;
- while(--ogzdir >= f.name && *ogzdir != PATHDIV);
- if(ogzdir < f.name || checkprefix(files, f.name, ogzdir + 1 - f.name))
- {
- if(ogzdir >= f.name)
- {
- stripdir = f.name;
- striplen = ogzdir + 1 - f.name;
- }
- if(!mountdir) mountdir = "packages/maps/";
- break;
- }
- }
- }
- string mdir = "", fname;
- if(mountdir)
- {
- copystring(mdir, mountdir);
- if(fixpackagedir(mdir) <= 1) mdir[0] = '\0';
- }
- loopv(files)
- {
- zipfile &f = files[i];
- formatstring(fname, "%s%s", mdir, striplen && !strncmp(f.name, stripdir, striplen) ? &f.name[striplen] : f.name);
- if(arch.files.access(fname)) continue;
- char *mname = newstring(fname);
- zipfile &mf = arch.files[mname];
- mf = f;
- mf.name = mname;
- }
+ string packagesdir = "packages/";
+ path(packagesdir);
+ size_t striplen = stripdir ? strlen(stripdir) : 0;
+ if(!mountdir && !stripdir) loopv(files)
+ {
+ zipfile &f = files[i];
+ const char *foundpackages = strstr(f.name, packagesdir);
+ if(foundpackages)
+ {
+ if(foundpackages > f.name)
+ {
+ stripdir = f.name;
+ striplen = foundpackages - f.name;
+ }
+ break;
+ }
+ const char *foundogz = strstr(f.name, ".ogz");
+ if(foundogz)
+ {
+ const char *ogzdir = foundogz;
+ while(--ogzdir >= f.name && *ogzdir != PATHDIV);
+ if(ogzdir < f.name || checkprefix(files, f.name, ogzdir + 1 - f.name))
+ {
+ if(ogzdir >= f.name)
+ {
+ stripdir = f.name;
+ striplen = ogzdir + 1 - f.name;
+ }
+ if(!mountdir) mountdir = "packages/maps/";
+ break;
+ }
+ }
+ }
+ string mdir = "", fname;
+ if(mountdir)
+ {
+ copystring(mdir, mountdir);
+ if(fixpackagedir(mdir) <= 1) mdir[0] = '\0';
+ }
+ loopv(files)
+ {
+ zipfile &f = files[i];
+ formatstring(fname, "%s%s", mdir, striplen && !strncmp(f.name, stripdir, striplen) ? &f.name[striplen] : f.name);
+ if(arch.files.access(fname)) continue;
+ char *mname = newstring(fname);
+ zipfile &mf = arch.files[mname];
+ mf = f;
+ mf.name = mname;
+ }
}
bool addzip(const char *name, const char *mount = NULL, const char *strip = NULL)
{
- string pname;
- copystring(pname, name);
- path(pname);
- size_t plen = strlen(pname);
- if(plen < 4 || !strchr(&pname[plen-4], '.')) concatstring(pname, ".zip");
-
- ziparchive *exists = findzip(pname);
- if(exists)
- {
- conoutf(CON_ERROR, "already added zip %s", pname);
- return true;
- }
-
- FILE *f = fopen(findfile(pname, "rb"), "rb");
- if(!f)
- {
- conoutf(CON_ERROR, "could not open file %s", pname);
- return false;
- }
- zipdirectoryheader h;
- vector<zipfile> files;
- if(!findzipdirectory(f, h) || !readzipdirectory(pname, f, h.entries, h.offset, h.size, files))
- {
- conoutf(CON_ERROR, "could not read directory in zip %s", pname);
- fclose(f);
- return false;
- }
-
- ziparchive *arch = new ziparchive;
- arch->name = newstring(pname);
- arch->data = f;
- mountzip(*arch, files, mount, strip);
- archives.add(arch);
-
- conoutf("added zip %s", pname);
- return true;
+ string pname;
+ copystring(pname, name);
+ path(pname);
+ size_t plen = strlen(pname);
+ if(plen < 4 || !strchr(&pname[plen-4], '.')) concatstring(pname, ".zip");
+
+ ziparchive *exists = findzip(pname);
+ if(exists)
+ {
+ conoutf(CON_ERROR, "already added zip %s", pname);
+ return true;
+ }
+
+ FILE *f = fopen(findfile(pname, "rb"), "rb");
+ if(!f)
+ {
+ conoutf(CON_ERROR, "could not open file %s", pname);
+ return false;
+ }
+ zipdirectoryheader h;
+ vector<zipfile> files;
+ if(!findzipdirectory(f, h) || !readzipdirectory(pname, f, h.entries, h.offset, h.size, files))
+ {
+ conoutf(CON_ERROR, "could not read directory in zip %s", pname);
+ fclose(f);
+ return false;
+ }
+
+ ziparchive *arch = new ziparchive;
+ arch->name = newstring(pname);
+ arch->data = f;
+ mountzip(*arch, files, mount, strip);
+ archives.add(arch);
+
+ conoutf("added zip %s", pname);
+ return true;
}
bool removezip(const char *name)
{
- string pname;
- copystring(pname, name);
- path(pname);
- int plen = (int)strlen(pname);
- if(plen < 4 || !strchr(&pname[plen-4], '.')) concatstring(pname, ".zip");
- ziparchive *exists = findzip(pname);
- if(!exists)
- {
- conoutf(CON_ERROR, "zip %s is not loaded", pname);
- return false;
- }
- if(exists->openfiles)
- {
- conoutf(CON_ERROR, "zip %s has open files", pname);
- return false;
- }
- conoutf("removed zip %s", exists->name);
- archives.removeobj(exists);
- delete exists;
- return true;
+ string pname;
+ copystring(pname, name);
+ path(pname);
+ int plen = (int)strlen(pname);
+ if(plen < 4 || !strchr(&pname[plen-4], '.')) concatstring(pname, ".zip");
+ ziparchive *exists = findzip(pname);
+ if(!exists)
+ {
+ conoutf(CON_ERROR, "zip %s is not loaded", pname);
+ return false;
+ }
+ if(exists->openfiles)
+ {
+ conoutf(CON_ERROR, "zip %s has open files", pname);
+ return false;
+ }
+ conoutf("removed zip %s", exists->name);
+ archives.removeobj(exists);
+ delete exists;
+ return true;
}
struct zipstream : stream
{
- enum
- {
- BUFSIZE = 16384
- };
-
- ziparchive *arch;
- zipfile *info;
- z_stream zfile;
- uchar *buf;
- uint reading;
- bool ended;
-
- zipstream() : arch(NULL), info(NULL), buf(NULL), reading(~0U), ended(false)
- {
- zfile.zalloc = NULL;
- zfile.zfree = NULL;
- zfile.opaque = NULL;
- zfile.next_in = zfile.next_out = NULL;
- zfile.avail_in = zfile.avail_out = 0;
- }
-
- ~zipstream()
- {
- close();
- }
-
- void readbuf(uint size = BUFSIZE)
- {
- if(!zfile.avail_in) zfile.next_in = (Bytef *)buf;
- size = min(size, uint(&buf[BUFSIZE] - &zfile.next_in[zfile.avail_in]));
- if(arch->owner != this)
- {
- arch->owner = NULL;
- if(fseek(arch->data, reading, SEEK_SET) >= 0) arch->owner = this;
- else return;
- }
- uint remaining = info->offset + info->compressedsize - reading,
- n = arch->owner == this ? fread(zfile.next_in + zfile.avail_in, 1, min(size, remaining), arch->data) : 0U;
- zfile.avail_in += n;
- reading += n;
- }
-
- bool open(ziparchive *a, zipfile *f)
- {
- if(f->offset == ~0U)
- {
- ziplocalfileheader h;
- a->owner = NULL;
- if(!readlocalfileheader(a->data, h, f->header)) return false;
- f->offset = f->header + ZIP_LOCAL_FILE_SIZE + h.namelength + h.extralength;
- }
-
- if(f->compressedsize && inflateInit2(&zfile, -MAX_WBITS) != Z_OK) return false;
-
- a->openfiles++;
- arch = a;
- info = f;
- reading = f->offset;
- ended = false;
- if(f->compressedsize) buf = new uchar[BUFSIZE];
- return true;
- }
-
- void stopreading()
- {
- if(reading == ~0U) return;
-#ifndef STANDALONE
- if(dbgzip) conoutf(CON_DEBUG, info->compressedsize ? "%s: zfile.total_out %u, info->size %u" : "%s: reading %u, info->size %u", info->name, info->compressedsize ? uint(zfile.total_out) : reading - info->offset, info->size);
-#endif
- if(info->compressedsize) inflateEnd(&zfile);
- reading = ~0U;
- }
-
- void close()
- {
- stopreading();
- DELETEA(buf);
- if(arch) { arch->owner = NULL; arch->openfiles--; arch = NULL; }
- }
-
- offset size() { return info->size; }
- bool end() { return reading == ~0U || ended; }
- offset tell() { return reading != ~0U ? (info->compressedsize ? zfile.total_out : reading - info->offset) : offset(-1); }
-
- bool seek(offset pos, int whence)
- {
- if(reading == ~0U) return false;
- if(!info->compressedsize)
- {
- switch(whence)
- {
- case SEEK_END: pos += info->offset + info->size; break;
- case SEEK_CUR: pos += reading; break;
- case SEEK_SET: pos += info->offset; break;
- default: return false;
- }
- pos = clamp(pos, offset(info->offset), offset(info->offset + info->size));
- arch->owner = NULL;
- if(fseek(arch->data, int(pos), SEEK_SET) < 0) return false;
- arch->owner = this;
- reading = pos;
- ended = false;
- return true;
- }
-
- switch(whence)
- {
- case SEEK_END: pos += info->size; break;
- case SEEK_CUR: pos += zfile.total_out; break;
- case SEEK_SET: break;
- default: return false;
- }
-
- if(pos >= (offset)info->size)
- {
- reading = info->offset + info->compressedsize;
- zfile.next_in += zfile.avail_in;
- zfile.avail_in = 0;
- zfile.total_in = info->compressedsize;
- zfile.total_out = info->size;
- arch->owner = NULL;
- ended = false;
- return true;
- }
-
- if(pos < 0) return false;
- if(pos >= (offset)zfile.total_out) pos -= zfile.total_out;
- else
- {
- if(zfile.next_in && zfile.total_in <= uint(zfile.next_in - buf))
- {
- zfile.avail_in += zfile.total_in;
- zfile.next_in -= zfile.total_in;
- }
- else
- {
- arch->owner = NULL;
- zfile.avail_in = 0;
- zfile.next_in = NULL;
- reading = info->offset;
- }
- inflateReset(&zfile);
- }
-
- uchar skip[512];
- while(pos > 0)
- {
- size_t skipped = (size_t)min(pos, (offset)sizeof(skip));
- if(read(skip, skipped) != skipped) return false;
- pos -= skipped;
- }
-
- ended = false;
- return true;
- }
-
- size_t read(void *buf, size_t len)
- {
- if(reading == ~0U || !buf || !len) return 0;
- if(!info->compressedsize)
- {
- if(arch->owner != this)
- {
- arch->owner = NULL;
- if(fseek(arch->data, reading, SEEK_SET) < 0) { stopreading(); return 0; }
- arch->owner = this;
- }
-
- size_t n = fread(buf, 1, min(len, size_t(info->size + info->offset - reading)), arch->data);
- reading += n;
- if(n < len) ended = true;
- return n;
- }
-
- zfile.next_out = (Bytef *)buf;
- zfile.avail_out = len;
- while(zfile.avail_out > 0)
- {
- if(!zfile.avail_in) readbuf(BUFSIZE);
- int err = inflate(&zfile, Z_NO_FLUSH);
- if(err != Z_OK)
- {
- if(err == Z_STREAM_END) ended = true;
- else
- {
-#ifndef STANDALONE
- if(dbgzip) conoutf(CON_DEBUG, "inflate error: %s", zError(err));
-#endif
- stopreading();
- }
- break;
- }
- }
- return len - zfile.avail_out;
- }
+ enum
+ {
+ BUFSIZE = 16384
+ };
+
+ ziparchive *arch;
+ zipfile *info;
+ z_stream zfile;
+ uchar *buf;
+ uint reading;
+ bool ended;
+
+ zipstream() : arch(NULL), info(NULL), buf(NULL), reading(~0U), ended(false)
+ {
+ zfile.zalloc = NULL;
+ zfile.zfree = NULL;
+ zfile.opaque = NULL;
+ zfile.next_in = zfile.next_out = NULL;
+ zfile.avail_in = zfile.avail_out = 0;
+ }
+
+ ~zipstream()
+ {
+ close();
+ }
+
+ void readbuf(uint size = BUFSIZE)
+ {
+ if(!zfile.avail_in) zfile.next_in = (Bytef *)buf;
+ size = min(size, uint(&buf[BUFSIZE] - &zfile.next_in[zfile.avail_in]));
+ if(arch->owner != this)
+ {
+ arch->owner = NULL;
+ if(fseek(arch->data, reading, SEEK_SET) >= 0) arch->owner = this;
+ else return;
+ }
+ uint remaining = info->offset + info->compressedsize - reading,
+ n = arch->owner == this ? fread(zfile.next_in + zfile.avail_in, 1, min(size, remaining), arch->data) : 0U;
+ zfile.avail_in += n;
+ reading += n;
+ }
+
+ bool open(ziparchive *a, zipfile *f)
+ {
+ if(f->offset == ~0U)
+ {
+ ziplocalfileheader h;
+ a->owner = NULL;
+ if(!readlocalfileheader(a->data, h, f->header)) return false;
+ f->offset = f->header + ZIP_LOCAL_FILE_SIZE + h.namelength + h.extralength;
+ }
+
+ if(f->compressedsize && inflateInit2(&zfile, -MAX_WBITS) != Z_OK) return false;
+
+ a->openfiles++;
+ arch = a;
+ info = f;
+ reading = f->offset;
+ ended = false;
+ if(f->compressedsize) buf = new uchar[BUFSIZE];
+ return true;
+ }
+
+ void stopreading()
+ {
+ if(reading == ~0U) return;
+ if(info->compressedsize) inflateEnd(&zfile);
+ reading = ~0U;
+ }
+
+ void close()
+ {
+ stopreading();
+ DELETEA(buf);
+ if(arch) { arch->owner = NULL; arch->openfiles--; arch = NULL; }
+ }
+
+ offset size() { return info->size; }
+ bool end() { return reading == ~0U || ended; }
+ offset tell() { return reading != ~0U ? (info->compressedsize ? zfile.total_out : reading - info->offset) : offset(-1); }
+
+ bool seek(offset pos, int whence)
+ {
+ if(reading == ~0U) return false;
+ if(!info->compressedsize)
+ {
+ switch(whence)
+ {
+ case SEEK_END: pos += info->offset + info->size; break;
+ case SEEK_CUR: pos += reading; break;
+ case SEEK_SET: pos += info->offset; break;
+ default: return false;
+ }
+ pos = clamp(pos, offset(info->offset), offset(info->offset + info->size));
+ arch->owner = NULL;
+ if(fseek(arch->data, int(pos), SEEK_SET) < 0) return false;
+ arch->owner = this;
+ reading = pos;
+ ended = false;
+ return true;
+ }
+
+ switch(whence)
+ {
+ case SEEK_END: pos += info->size; break;
+ case SEEK_CUR: pos += zfile.total_out; break;
+ case SEEK_SET: break;
+ default: return false;
+ }
+
+ if(pos >= (offset)info->size)
+ {
+ reading = info->offset + info->compressedsize;
+ zfile.next_in += zfile.avail_in;
+ zfile.avail_in = 0;
+ zfile.total_in = info->compressedsize;
+ zfile.total_out = info->size;
+ arch->owner = NULL;
+ ended = false;
+ return true;
+ }
+
+ if(pos < 0) return false;
+ if(pos >= (offset)zfile.total_out) pos -= zfile.total_out;
+ else
+ {
+ if(zfile.next_in && zfile.total_in <= uint(zfile.next_in - buf))
+ {
+ zfile.avail_in += zfile.total_in;
+ zfile.next_in -= zfile.total_in;
+ }
+ else
+ {
+ arch->owner = NULL;
+ zfile.avail_in = 0;
+ zfile.next_in = NULL;
+ reading = info->offset;
+ }
+ inflateReset(&zfile);
+ }
+
+ uchar skip[512];
+ while(pos > 0)
+ {
+ size_t skipped = (size_t)min(pos, (offset)sizeof(skip));
+ if(read(skip, skipped) != skipped) return false;
+ pos -= skipped;
+ }
+
+ ended = false;
+ return true;
+ }
+
+ size_t read(void *buf, size_t len)
+ {
+ if(reading == ~0U || !buf || !len) return 0;
+ if(!info->compressedsize)
+ {
+ if(arch->owner != this)
+ {
+ arch->owner = NULL;
+ if(fseek(arch->data, reading, SEEK_SET) < 0) { stopreading(); return 0; }
+ arch->owner = this;
+ }
+
+ size_t n = fread(buf, 1, min(len, size_t(info->size + info->offset - reading)), arch->data);
+ reading += n;
+ if(n < len) ended = true;
+ return n;
+ }
+
+ zfile.next_out = (Bytef *)buf;
+ zfile.avail_out = len;
+ while(zfile.avail_out > 0)
+ {
+ if(!zfile.avail_in) readbuf(BUFSIZE);
+ int err = inflate(&zfile, Z_NO_FLUSH);
+ if(err != Z_OK)
+ {
+ if(err == Z_STREAM_END) ended = true;
+ else stopreading();
+ break;
+ }
+ }
+ return len - zfile.avail_out;
+ }
};
stream *openzipfile(const char *name, const char *mode)
{
- for(; *mode; mode++) if(*mode=='w' || *mode=='a') return NULL;
- loopvrev(archives)
- {
- ziparchive *arch = archives[i];
- zipfile *f = arch->files.access(name);
- if(!f) continue;
- zipstream *s = new zipstream;
- if(s->open(arch, f)) return s;
- delete s;
- }
- return NULL;
+ for(; *mode; mode++) if(*mode=='w' || *mode=='a') return NULL;
+ loopvrev(archives)
+ {
+ ziparchive *arch = archives[i];
+ zipfile *f = arch->files.access(name);
+ if(!f) continue;
+ zipstream *s = new zipstream;
+ if(s->open(arch, f)) return s;
+ delete s;
+ }
+ return NULL;
}
bool findzipfile(const char *name)
{
- loopvrev(archives)
- {
- ziparchive *arch = archives[i];
- if(arch->files.access(name)) return true;
- }
- return false;
+ loopvrev(archives)
+ {
+ ziparchive *arch = archives[i];
+ if(arch->files.access(name)) return true;
+ }
+ return false;
}
int listzipfiles(const char *dir, const char *ext, vector<char *> &files)
{
- size_t extsize = ext ? strlen(ext)+1 : 0, dirsize = strlen(dir);
- int dirs = 0;
- loopvrev(archives)
- {
- ziparchive *arch = archives[i];
- int oldsize = files.length();
- enumerate(arch->files, zipfile, f,
- {
- if(strncmp(f.name, dir, dirsize)) continue;
- const char *name = f.name + dirsize;
- if(name[0] == PATHDIV) name++;
- if(strchr(name, PATHDIV)) continue;
- if(!ext) files.add(newstring(name));
- else
- {
- size_t namelen = strlen(name);
- if(namelen > extsize)
- {
- namelen -= extsize;
- if(name[namelen] == '.' && strncmp(name+namelen+1, ext, extsize-1)==0)
- files.add(newstring(name, namelen));
- }
- }
- });
- if(files.length() > oldsize) dirs++;
- }
- return dirs;
+ size_t extsize = ext ? strlen(ext)+1 : 0, dirsize = strlen(dir);
+ int dirs = 0;
+ loopvrev(archives)
+ {
+ ziparchive *arch = archives[i];
+ int oldsize = files.length();
+ enumerate(arch->files, zipfile, f,
+ {
+ if(strncmp(f.name, dir, dirsize)) continue;
+ const char *name = f.name + dirsize;
+ if(name[0] == PATHDIV) name++;
+ if(strchr(name, PATHDIV)) continue;
+ if(!ext) files.add(newstring(name));
+ else
+ {
+ size_t namelen = strlen(name);
+ if(namelen > extsize)
+ {
+ namelen -= extsize;
+ if(name[namelen] == '.' && strncmp(name+namelen+1, ext, extsize-1)==0)
+ files.add(newstring(name, namelen));
+ }
+ }
+ });
+ if(files.length() > oldsize) dirs++;
+ }
+ return dirs;
}
#ifndef STANDALONE