diff options
| author | xolatile | 2025-08-04 22:53:42 +0200 |
|---|---|---|
| committer | xolatile | 2025-08-04 22:53:42 +0200 |
| commit | d309df4ce4d8ad0ed995a8e1c4267412a7782021 (patch) | |
| tree | 999ca8d785ecc1681e5eb7538ce2e6a18d244fa5 /src/shared | |
| parent | 29d613d9cb65a0faa7e3f80e75bea0b6d910cb9a (diff) | |
| download | xolatile-badassbug-d309df4ce4d8ad0ed995a8e1c4267412a7782021.tar.xz xolatile-badassbug-d309df4ce4d8ad0ed995a8e1c4267412a7782021.tar.zst | |
Bunch of small changes...
Diffstat (limited to 'src/shared')
| -rw-r--r-- | src/shared/command.h | 378 | ||||
| -rw-r--r-- | src/shared/crypto.cpp | 1630 | ||||
| -rw-r--r-- | src/shared/cube.h | 32 | ||||
| -rw-r--r-- | src/shared/cube2font.c | 876 | ||||
| -rw-r--r-- | src/shared/ents.h | 328 | ||||
| -rw-r--r-- | src/shared/geom.cpp | 444 | ||||
| -rw-r--r-- | src/shared/geom.h | 3202 | ||||
| -rw-r--r-- | src/shared/glemu.cpp | 692 | ||||
| -rw-r--r-- | src/shared/glemu.h | 352 | ||||
| -rw-r--r-- | src/shared/glexts.h | 485 | ||||
| -rw-r--r-- | src/shared/iengine.h | 318 | ||||
| -rw-r--r-- | src/shared/igame.h | 218 | ||||
| -rw-r--r-- | src/shared/stream.cpp | 2012 | ||||
| -rw-r--r-- | src/shared/tools.cpp | 276 | ||||
| -rw-r--r-- | src/shared/tools.h | 1878 | ||||
| -rw-r--r-- | src/shared/zip.cpp | 994 |
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 ¢er, 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 ¢er, 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 ¢er, 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 ¬found) - { - HTFIND( , notfound); - } - - template<class U> - const T &find(const U &key, const T ¬found) - { - 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 ¬found) + { + HTFIND( , notfound); + } + + template<class U> + const T &find(const U &key, const T ¬found) + { + 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 |
