1 #ifndef H_UTILS
2 #define H_UTILS
3
4 #include <stdlib.h>
5 #include <math.h>
6 #include <float.h>
7
8 //#define TEST_SLOW_FIO
9
10 #ifdef _DEBUG
11 #if defined(_OS_LINUX) || defined(_OS_RPI) || defined(_OS_CLOVER)
12 #define debugBreak() raise(SIGTRAP);
13 #elif defined(_OS_3DS)
14 #define debugBreak() svcBreak(USERBREAK_ASSERT);
15 #else
16 #define debugBreak() _asm { int 3 }
17 #endif
18
19 #define ASSERT(expr) if (expr) {} else { LOG("ASSERT:\n %s:%d\n %s => %s\n", __FILE__, __LINE__, __FUNCTION__, #expr); debugBreak(); }
20 #define ASSERTV(expr) ASSERT(expr)
21
22 #ifndef _OS_ANDROID
23 #define LOG printf
24 #endif
25
26 #if defined(_OS_XBOX) || defined(_OS_XB1)
27 #define MAX_LOG_LENGTH 1024
28
29 #undef LOG
LOG(const char * format,...)30 void LOG(const char *format, ...) {
31 char str[MAX_LOG_LENGTH];
32 va_list arglist;
33 va_start(arglist, format);
34 _vsnprintf(str, MAX_LOG_LENGTH, format, arglist);
35 va_end(arglist);
36 OutputDebugStringA(str);
37 }
38 #endif
39
40 #else
41
42 #define ASSERT(expr)
43 #define ASSERTV(expr) (expr) ? 1 : 0
44
45 #ifdef PROFILE
46 #ifdef _OS_LINUX
47 #define LOG(...) printf(__VA_ARGS__); fflush(stdout)
48 #else
49 #define LOG(...) printf(__VA_ARGS__)
50 #endif
51 #else
52 #define LOG printf
53 #endif
54 #endif
55
56 #ifdef _OS_PSV
57 #undef LOG
58 #define LOG(...) psvDebugScreenPrintf(__VA_ARGS__)
59 #endif
60
61 #ifdef _OS_ANDROID
62 #include <android/log.h>
63 #undef LOG
64 #define LOG(...) __android_log_print(ANDROID_LOG_INFO,"OpenLara",__VA_ARGS__)
65 #endif
66
67
68 #ifdef _OS_PSP
69 extern "C" {
70 // pspmath.h
71 extern float vfpu_sinf(float x);
72 extern float vfpu_cosf(float x);
73 extern float vfpu_atan2f(float x, float y);
74 extern void vfpu_sincos(float r, float *s, float *c);
75 }
76
77 #define sinf(x) vfpu_sinf(x)
78 #define cosf(x) vfpu_cosf(x)
79 #define atan2f(x, y) vfpu_atan2f(x, y)
80 #define sincos(a, s, c) vfpu_sincos(a, s, c)
81 #else
sincos(float r,float * s,float * c)82 void sincos(float r, float *s, float *c) {
83 *s = sinf(r);
84 *c = cosf(r);
85 }
86 #endif
87
88 #define DECL_ENUM(v) v,
89 #define DECL_STR(v) #v,
90
91 #define EPS FLT_EPSILON
92 #define INF FLT_MAX
93 #define PI 3.14159265358979323846f
94 #define PIH (PI * 0.5f)
95 #define PI2 (PI * 2.0f)
96 #define DEG2RAD (PI / 180.0f)
97 #define RAD2DEG (180.0f / PI)
98
99 #define COS30 0.86602540378f
100 #define COS45 0.70710678118f
101 #define COS60 0.50000000000f
102
103 #define SQR(x) ((x)*(x))
104 #define randf() (float(rand())/float(RAND_MAX))
105
106 typedef signed char int8;
107 typedef signed short int16;
108 typedef signed int int32;
109 typedef signed long long int64;
110 typedef unsigned char uint8;
111 typedef unsigned short uint16;
112 typedef unsigned int uint32;
113 typedef unsigned long long uint64;
114
115 #define FOURCC(str) uint32( ((uint8*)(str))[0] | (((uint8*)(str))[1] << 8) | (((uint8*)(str))[2] << 16) | (((uint8*)(str))[3] << 24) )
116 #define TWOCC(str) uint32( ((uint8*)(str))[0] | (((uint8*)(str))[1] << 8) )
117
118 #define ALIGNADDR(x, a) (((x) + ((a) - 1)) & ~((a) - 1))
119 #define COUNT(arr) int(sizeof(arr) / sizeof(arr[0]))
120 #define OFFSETOF(T, E) ((size_t)&(((T*)0)->E))
121 #define TEST_BIT(arr, bit) ((arr[bit / 32] >> (bit % 32)) & 1)
122
123 template <typename T>
min(const T & a,const T & b)124 inline const T& min(const T &a, const T &b) {
125 return a < b ? a : b;
126 }
127
128 template <typename T>
min(const T & a,const T & b,const T & c)129 inline const T& min(const T &a, const T &b, const T &c) {
130 return (a < b && a < c) ? a : ((b < a && b < c) ? b : c);
131 }
132
133 template <class T>
max(const T & a,const T & b)134 inline const T& max(const T &a, const T &b) {
135 return a > b ? a : b;
136 }
137
138 template <typename T>
max(const T & a,const T & b,const T & c)139 inline const T& max(const T &a, const T &b, const T &c) {
140 return (a > b && a > c) ? a : ((b > a && b > c) ? b : c);
141 }
142
143 template <class T>
clamp(const T & x,const T & a,const T & b)144 inline const T& clamp(const T &x, const T &a, const T &b) {
145 return x < a ? a : (x > b ? b : x);
146 }
147
148 template <class T>
sign(const T & x)149 inline const T sign(const T &x) {
150 return (T)(x > 0 ? 1 : (x < 0 ? -1 : 0));
151 }
152
153 template <class T>
swap(T & a,T & b)154 inline void swap(T &a, T &b) {
155 T tmp = a;
156 a = b;
157 b = tmp;
158 }
159
swap16(uint16 x)160 inline uint16 swap16(uint16 x) {
161 return ((x & 0x00FF) << 8) | ((x & 0xFF00) >> 8);
162 }
163
swap32(uint32 x)164 inline uint32 swap32(uint32 x) {
165 return ((x & 0x000000FF) << 24) | ((x & 0x0000FF00) << 8) | ((x & 0x00FF0000) >> 8) | ((x & 0xFF000000) >> 24);
166 }
167
clampAngle(float a)168 float clampAngle(float a) {
169 return a < -PI ? a + PI2 : (a >= PI ? a - PI2 : a);
170 }
171
shortAngle(float a,float b)172 float shortAngle(float a, float b) {
173 float n = clampAngle(b) - clampAngle(a);
174 return clampAngle(n - int(n / PI2) * PI2);
175 }
176
normalizeAngle(float angle)177 float normalizeAngle(float angle) {
178 while (angle < 0.0f) angle += PI2;
179 while (angle > PI2) angle -= PI2;
180 return angle;
181 }
182
angleQuadrant(float angle,float offset)183 int angleQuadrant(float angle, float offset) {
184 return int(normalizeAngle(angle + PI * offset) / (PI * 0.5f));
185 }
186
decrease(float delta,float & value,float & speed)187 float decrease(float delta, float &value, float &speed) {
188 if (speed > 0.0f && fabsf(delta) > 0.001f) {
189 if (delta > 0) speed = min(delta, speed);
190 if (delta < 0) speed = max(delta, -speed);
191 value += speed;
192 return speed;
193 } else
194 return 0.0f;
195 }
196
hermite(float x)197 inline float hermite(float x) {
198 return x * x * (3 - 2 * x);
199 }
200
quintic(float x)201 inline float quintic(float x) {
202 return x * x * x * (x * (x * 6 - 15) + 10);
203 }
204
lerp(float a,float b,float t)205 inline float lerp(float a, float b, float t) {
206 if (t <= 0.0f) return a;
207 if (t >= 1.0f) return b;
208 return a + (b - a) * t;
209 }
210
lerpAngle(float a,float b,float t)211 float lerpAngle(float a, float b, float t) {
212 if (t <= 0.0f) return a;
213 if (t >= 1.0f) return b;
214 return a + shortAngle(a, b) * t;
215 }
216
nextPow2(uint32 x)217 int nextPow2(uint32 x) {
218 x--;
219 x |= x >> 1;
220 x |= x >> 2;
221 x |= x >> 4;
222 x |= x >> 8;
223 x |= x >> 16;
224 x++;
225 return x;
226 }
227
log2i(uint32 value)228 inline uint32 log2i(uint32 value) {
229 int res = 0;
230 for(; value; value >>= 1, res++);
231 return res ? res - 1 : res;
232 }
233
234 uint32 fnv32(const char *data, int32 size, uint32 hash = 0x811c9dc5) {
235 for (int i = 0; i < size; i++)
236 hash = (hash ^ data[i]) * 0x01000193;
237 return hash;
238 }
239
240 template <class T>
qsort(T * v,int L,int R)241 void qsort(T* v, int L, int R) {
242 int i = L;
243 int j = R;
244 const T m = v[(L + R) / 2];
245
246 while (i <= j) {
247 while (T::cmp(v[i], m) < 0) i++;
248 while (T::cmp(m, v[j]) < 0) j--;
249
250 if (i <= j)
251 swap(v[i++], v[j--]);
252 }
253
254 if (L < j) qsort(v, L, j);
255 if (i < R) qsort(v, i, R);
256 }
257
258 template <class T>
sort(T * items,int count)259 void sort(T *items, int count) {
260 if (count)
261 qsort(items, 0, count - 1);
262 }
263
264
265 namespace Noise { // based on https://github.com/Auburns/FastNoise
266 int seed;
267
268 uint8 m_perm[512];
269 uint8 m_perm12[512];
270
271 const float GRAD_X[] = { 1, -1, 1, -1, 1, -1, 1, -1, 0, 0, 0, 0 };
272 const float GRAD_Y[] = { 1, 1, -1, -1, 0, 0, 0, 0, 1, -1, 1, -1 };
273 const float GRAD_Z[] = { 0, 0, 0, 0, 1, 1, -1, -1, 1, 1, -1, -1 };
274
index(int x,int y,int z)275 uint8 index(int x, int y, int z) {
276 return m_perm12[(x & 0xff) + m_perm[(y & 0xff) + m_perm[(z & 0xff)]]];
277 }
278
noise(int x,int y,int z,float xd,float yd,float zd)279 float noise(int x, int y, int z, float xd, float yd, float zd) {
280 uint8 lutPos = index(x, y, z);
281 return xd * GRAD_X[lutPos] + yd * GRAD_Y[lutPos] + zd * GRAD_Z[lutPos];
282 }
283
setSeed(int seed)284 void setSeed(int seed) {
285 Noise::seed = seed;
286 srand(seed);
287
288 for (int i = 0; i < 256; i++)
289 m_perm[i] = i;
290
291 for (int j = 0; j < 256; j++) {
292 int k = (rand() % (256 - j)) + j;
293 int p = m_perm[j];
294 m_perm[j] = m_perm[j + 256] = m_perm[k];
295 m_perm[k] = p;
296 m_perm12[j] = m_perm12[j + 256] = m_perm[j] % 12;
297 }
298 }
299
value(float x,float y,float z,int size)300 float value(float x, float y, float z, int size) {
301 x *= size;
302 y *= size;
303 z *= size;
304
305 int x0 = (int)x;
306 int y0 = (int)y;
307 int z0 = (int)z;
308 int x1 = (x0 + 1) % size;
309 int y1 = (y0 + 1) % size;
310 int z1 = (z0 + 1) % size;
311
312 float dx0 = x - x0;
313 float dy0 = y - y0;
314 float dz0 = z - z0;
315 float dx1 = dx0 - 1;
316 float dy1 = dy0 - 1;
317 float dz1 = dz0 - 1;
318
319 float fx = quintic(dx0);
320 float fy = quintic(dy0);
321 float fz = quintic(dz0);
322
323 return lerp(lerp(lerp(noise(x0, y0, z0, dx0, dy0, dz0), noise(x1, y0, z0, dx1, dy0, dz0), fx),
324 lerp(noise(x0, y1, z0, dx0, dy1, dz0), noise(x1, y1, z0, dx1, dy1, dz0), fx), fy),
325 lerp(lerp(noise(x0, y0, z1, dx0, dy0, dz1), noise(x1, y0, z1, dx1, dy0, dz1), fx),
326 lerp(noise(x0, y1, z1, dx0, dy1, dz1), noise(x1, y1, z1, dx1, dy1, dz1), fx), fy), fz);
327 }
328
generate(uint32 seed,int size,int octaves,int frequency,float amplitude)329 uint8* generate(uint32 seed, int size, int octaves, int frequency, float amplitude) {
330 setSeed(seed);
331
332 float *out = new float[size * size * size];
333 memset(out, 0, size * size * size * sizeof(float));
334
335 float isize = 1.0f / size;
336
337 for (int j = 0; j < octaves; j++) {
338 float *ptr = out;
339
340 for (int z = 0; z < size; z++) {
341 float iz = z * isize;
342 for (int y = 0; y < size; y++) {
343 float iy = y * isize;
344 for (int x = 0; x < size; x++) {
345 float ix = x * isize;
346 *ptr++ += value(ix, iy, iz, frequency) * amplitude;
347 }
348 }
349 }
350
351 frequency *= 2;
352 amplitude *= 0.5f;
353 }
354
355 uint8 *dst = new uint8[size * size * size];
356 for (int i = 0; i < size * size * size; i++) {
357 dst[i] = clamp(int((out[i] * 0.5f + 0.5f) * 255.0f), 0, 255);
358 }
359
360 delete[] out;
361
362 return dst;
363 }
364 }
365
366 struct vec2 {
367 float x, y;
vec2vec2368 vec2() {}
vec2vec2369 vec2(float s) : x(s), y(s) {}
vec2vec2370 vec2(float x, float y) : x(x), y(y) {}
371
372 inline float& operator [] (int index) const { ASSERT(index >= 0 && index <= 1); return ((float*)this)[index]; }
373
374 inline bool operator == (const vec2 &v) const { return x == v.x && y == v.y; }
375 inline bool operator != (const vec2 &v) const { return !(*this == v); }
376 inline bool operator == (float s) const { return x == s && y == s; }
377 inline bool operator != (float s) const { return !(*this == s); }
378 inline bool operator < (const vec2 &v) const { return x < v.x && y < v.y; }
379 inline bool operator > (const vec2 &v) const { return x > v.x && y > v.y; }
380 inline vec2 operator - () const { return vec2(-x, -y); }
381
382 vec2& operator += (const vec2 &v) { x += v.x; y += v.y; return *this; }
383 vec2& operator -= (const vec2 &v) { x -= v.x; y -= v.y; return *this; }
384 vec2& operator *= (const vec2 &v) { x *= v.x; y *= v.y; return *this; }
385 vec2& operator /= (const vec2 &v) { x /= v.x; y /= v.y; return *this; }
386 vec2& operator += (float s) { x += s; y += s; return *this; }
387 vec2& operator -= (float s) { x -= s; y -= s; return *this; }
388 vec2& operator *= (float s) { x *= s; y *= s; return *this; }
389 vec2& operator /= (float s) { x /= s; y /= s; return *this; }
390
391 vec2 operator + (const vec2 &v) const { return vec2(x + v.x, y + v.y); }
392 vec2 operator - (const vec2 &v) const { return vec2(x - v.x, y - v.y); }
393 vec2 operator * (const vec2 &v) const { return vec2(x * v.x, y * v.y); }
394 vec2 operator / (const vec2 &v) const { return vec2(x / v.x, y / v.y); }
395 vec2 operator + (float s) const { return vec2(x + s, y + s ); }
396 vec2 operator - (float s) const { return vec2(x - s, y - s ); }
397 vec2 operator * (float s) const { return vec2(x * s, y * s ); }
398 vec2 operator / (float s) const { return vec2(x / s, y / s ); }
399
dotvec2400 float dot(const vec2 &v) const { return x * v.x + y * v.y; }
crossvec2401 float cross(const vec2 &v) const { return x * v.y - y * v.x; }
402
length2vec2403 float length2() const { return dot(*this); }
lengthvec2404 float length() const { return sqrtf(length2()); }
absvec2405 vec2 abs() const { return vec2(fabsf(x), fabsf(y)); }
normalvec2406 vec2 normal() const { float s = length(); return s == 0.0 ? (*this) : (*this)*(1.0f/s); }
anglevec2407 float angle() const { return atan2f(y, x); }
rotatevec2408 vec2& rotate(const vec2 &cs) { *this = vec2(x*cs.x - y*cs.y, x*cs.y + y*cs.x); return *this; }
rotatevec2409 vec2& rotate(float angle) { vec2 cs; sincos(angle, &cs.y, &cs.x); return rotate(cs); }
410
lerpvec2411 vec2 lerp(const vec2 &v, const float t) const {
412 if (t <= 0.0f) return *this;
413 if (t >= 1.0f) return v;
414 return *this + (v - *this) * t;
415 }
416 };
417
418 struct vec3 {
419 float x, y, z;
420
vec3vec3421 vec3() {}
vec3vec3422 vec3(float s) : x(s), y(s), z(s) {}
vec3vec3423 vec3(float x, float y, float z) : x(x), y(y), z(z) {}
424 vec3(const vec2 &xy, float z = 0.0f) : x(xy.x), y(xy.y), z(z) {}
vec3vec3425 vec3(float lng, float lat) : x(sinf(lat) * cosf(lng)), y(-sinf(lng)), z(cosf(lat) * cosf(lng)) {}
426
xyvec3427 vec2& xy() const { return *((vec2*)&x); }
yzvec3428 vec2& yz() const { return *((vec2*)&y); }
429
430 inline float& operator [] (int index) const { ASSERT(index >= 0 && index <= 2); return ((float*)this)[index]; }
431
432 inline bool operator == (const vec3 &v) const { return x == v.x && y == v.y && z == v.z; }
433 inline bool operator != (const vec3 &v) const { return !(*this == v); }
434 inline bool operator == (float s) const { return x == s && y == s && z == s; }
435 inline bool operator != (float s) const { return !(*this == s); }
436 inline bool operator < (const vec3 &v) const { return x < v.x && y < v.y && z < v.z; }
437 inline bool operator > (const vec3 &v) const { return x > v.x && y > v.y && z > v.z; }
438 inline vec3 operator - () const { return vec3(-x, -y, -z); }
439
440 vec3& operator += (const vec3 &v) { x += v.x; y += v.y; z += v.z; return *this; }
441 vec3& operator -= (const vec3 &v) { x -= v.x; y -= v.y; z -= v.z; return *this; }
442 vec3& operator *= (const vec3 &v) { x *= v.x; y *= v.y; z *= v.z; return *this; }
443 vec3& operator /= (const vec3 &v) { x /= v.x; y /= v.y; z /= v.z; return *this; }
444 vec3& operator += (float s) { x += s; y += s; z += s; return *this; }
445 vec3& operator -= (float s) { x -= s; y -= s; z -= s; return *this; }
446 vec3& operator *= (float s) { x *= s; y *= s; z *= s; return *this; }
447 vec3& operator /= (float s) { x /= s; y /= s; z /= s; return *this; }
448
449 vec3 operator + (const vec3 &v) const { return vec3(x + v.x, y + v.y, z + v.z); }
450 vec3 operator - (const vec3 &v) const { return vec3(x - v.x, y - v.y, z - v.z); }
451 vec3 operator * (const vec3 &v) const { return vec3(x * v.x, y * v.y, z * v.z); }
452 vec3 operator / (const vec3 &v) const { return vec3(x / v.x, y / v.y, z / v.z); }
453 vec3 operator + (float s) const { return vec3(x + s, y + s, z + s); }
454 vec3 operator - (float s) const { return vec3(x - s, y - s, z - s); }
455 vec3 operator * (float s) const { return vec3(x * s, y * s, z * s); }
456 vec3 operator / (float s) const { return vec3(x / s, y / s, z / s); }
457
dotvec3458 float dot(const vec3 &v) const { return x * v.x + y * v.y + z * v.z; }
crossvec3459 vec3 cross(const vec3 &v) const { return vec3(y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x); }
460
length2vec3461 float length2() const { return dot(*this); }
lengthvec3462 float length() const { return sqrtf(length2()); }
absvec3463 vec3 abs() const { return vec3(fabsf(x), fabsf(y), fabsf(z)); }
normalvec3464 vec3 normal() const { float s = length(); return s == 0.0f ? (*this) : (*this)*(1.0f/s); }
axisXZvec3465 vec3 axisXZ() const { return (fabsf(x) > fabsf(z)) ? vec3(float(sign(x)), 0, 0) : vec3(0, 0, float(sign(z))); }
466
reflectvec3467 vec3 reflect(const vec3 &n) const {
468 return *this - n * (dot(n) * 2.0f);
469 }
470
lerpvec3471 vec3 lerp(const vec3 &v, const float t) const {
472 if (t <= 0.0f) return *this;
473 if (t >= 1.0f) return v;
474 return *this + (v - *this) * t;
475 }
476
rotateYvec3477 vec3 rotateY(float angle) const {
478 float s, c;
479 sincos(angle, &s, &c);
480 return vec3(x*c - z*s, y, x*s + z*c);
481 }
482
anglevec3483 float angle(const vec3 &v) const {
484 return dot(v) / (length() * v.length());
485 }
486
angleXvec3487 float angleX() const { return atan2f(sqrtf(x * x + z * z), y); }
angleYvec3488 float angleY() const { return atan2f(z, x); }
489 };
490
491 struct vec4 {
492 float x, y, z, w;
493
xyvec4494 vec2& xy() const { return *((vec2*)&x); }
xyzvec4495 vec3& xyz() const { return *((vec3*)&x); }
496
vec4vec4497 vec4() {}
vec4vec4498 vec4(float s) : x(s), y(s), z(s), w(s) {}
vec4vec4499 vec4(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) {}
vec4vec4500 vec4(const vec3 &xyz) : x(xyz.x), y(xyz.y), z(xyz.z), w(0) {}
vec4vec4501 vec4(const vec3 &xyz, float w) : x(xyz.x), y(xyz.y), z(xyz.z), w(w) {}
vec4vec4502 vec4(const vec2 &xy, const vec2 &zw) : x(xy.x), y(xy.y), z(zw.x), w(zw.y) {}
503
504 inline float& operator [] (int index) const { ASSERT(index >= 0 && index <= 3); return ((float*)this)[index]; }
505
506 inline bool operator == (const vec4 &v) const { return x == v.x && y == v.y && z == v.z && w == v.w; }
507 inline bool operator != (const vec4 &v) const { return !(*this == v); }
508
509 vec4 operator + (const vec4 &v) const { return vec4(x + v.x, y + v.y, z + v.z, w + v.w); }
510 vec4 operator - (const vec4 &v) const { return vec4(x - v.x, y - v.y, z - v.z, w - v.w); }
511 vec4 operator * (const vec4 &v) const { return vec4(x*v.x, y*v.y, z*v.z, w*v.w); }
512 vec4& operator *= (const vec4 &v) { x*=v.x; y*=v.y; z*=v.z; w*=v.w; return *this; }
513
dotvec4514 float dot(const vec4 &v) const { return x * v.x + y * v.y + z * v.z + w * v.w; }
515
lerpvec4516 vec4 lerp(const vec4 &v, const float t) const {
517 if (t <= 0.0f) return *this;
518 if (t >= 1.0f) return v;
519 return *this + (v - *this) * t;
520 }
521 };
522
523 struct quat {
524 float x, y, z, w;
525
xyzquat526 vec3& xyz() const { return *((vec3*)&x); }
527
quatquat528 quat() {}
quatquat529 quat(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) {}
530
quatquat531 quat(const vec3 &axis, float angle) {
532 float s, c;
533 sincos(angle * 0.5f, &s, &c);
534 x = axis.x * s;
535 y = axis.y * s;
536 z = axis.z * s;
537 w = c;
538 }
539
540 inline bool operator == (const quat &q) const { return x == q.x && y == q.y && z == q.z && w == q.w; }
541 inline bool operator != (const quat &v) const { return !(*this == v); }
542
543 quat operator - () const {
544 return quat(-x, -y, -z, -w);
545 }
546
547 quat operator + (const quat &q) const {
548 return quat(x + q.x, y + q.y, z + q.z, w + q.w);
549 }
550
551 quat operator - (const quat &q) const {
552 return quat(x - q.x, y - q.y, z - q.z, w - q.w);
553 }
554
555 quat operator * (const float s) const {
556 return quat(x * s, y * s, z * s, w * s);
557 }
558
559 quat operator * (const quat &q) const {
560 return quat(w * q.x + x * q.w + y * q.z - z * q.y,
561 w * q.y + y * q.w + z * q.x - x * q.z,
562 w * q.z + z * q.w + x * q.y - y * q.x,
563 w * q.w - x * q.x - y * q.y - z * q.z);
564 }
565
566 vec3 operator * (const vec3 &v) const {
567 return v + xyz().cross(xyz().cross(v) + v * w) * 2.0f;
568 }
569
dotquat570 float dot(const quat &q) const {
571 return x * q.x + y * q.y + z * q.z + w * q.w;
572 }
573
length2quat574 float length2() const {
575 return dot(*this);
576 }
577
lengthquat578 float length() const {
579 return sqrtf(length2());
580 }
581
normalizequat582 void normalize() {
583 *this = normal();
584 }
585
normalquat586 quat normal() const {
587 return *this * (1.0f / length());
588 }
589
conjugatequat590 quat conjugate() const {
591 return quat(-x, -y, -z, w);
592 }
593
inversequat594 quat inverse() const {
595 return conjugate() * (1.0f / length2());
596 }
597
lerpquat598 quat lerp(const quat &q, float t) const {
599 if (t <= 0.0f) return *this;
600 if (t >= 1.0f) return q;
601
602 return dot(q) < 0 ? (*this - (q + *this) * t) :
603 (*this + (q - *this) * t);
604 }
605
slerpquat606 quat slerp(const quat &q, float t) const {
607 if (t <= 0.0f) return *this;
608 if (t >= 1.0f) return q;
609
610 quat temp;
611 float omega, cosom, sinom, scale0, scale1;
612
613 cosom = dot(q);
614 if (cosom < 0.0f) {
615 temp = -q;
616 cosom = -cosom;
617 } else
618 temp = q;
619
620 if (1.0f - cosom > EPS) {
621 omega = acosf(cosom);
622 sinom = 1.0f / sinf(omega);
623 scale0 = sinf((1.0f - t) * omega) * sinom;
624 scale1 = sinf(t * omega) * sinom;
625 } else {
626 scale0 = 1.0f - t;
627 scale1 = t;
628 }
629
630 return *this * scale0 + temp * scale1;
631 }
632 };
633
634 struct mat4 {
635
636 enum ProjRange {
637 PROJ_NEG_POS,
638 PROJ_NEG_ZERO,
639 PROJ_ZERO_POS,
640 };
641
642 float e00, e10, e20, e30,
643 e01, e11, e21, e31,
644 e02, e12, e22, e32,
645 e03, e13, e23, e33;
646
rightmat4647 vec4& right() const { return *((vec4*)&e00); }
upmat4648 vec4& up() const { return *((vec4*)&e01); }
dirmat4649 vec4& dir() const { return *((vec4*)&e02); }
offsetmat4650 vec4& offset() const { return *((vec4*)&e03); }
651
mat4mat4652 mat4() {}
653
mat4mat4654 mat4(float e00, float e10, float e20, float e30,
655 float e01, float e11, float e21, float e31,
656 float e02, float e12, float e22, float e32,
657 float e03, float e13, float e23, float e33) :
658 e00(e00), e10(e10), e20(e20), e30(e30),
659 e01(e01), e11(e11), e21(e21), e31(e31),
660 e02(e02), e12(e12), e22(e22), e32(e32),
661 e03(e03), e13(e13), e23(e23), e33(e33) {}
662
mat4mat4663 mat4(const quat &rot, const vec3 &pos) {
664 setRot(rot);
665 setPos(pos);
666 e30 = e31 = e32 = 0.0f;
667 e33 = 1.0f;
668 }
669
670 void ortho(ProjRange range, float l, float r, float b, float t, float znear, float zfar, bool rotate90 = false) {
671 identity();
672
673 if (rotate90) {
674 e00 = e11 = 0.0f;
675 e10 = 2.0f / (l - r);
676 e01 = 2.0f / (t - b);
677 } else {
678 e00 = 2.0f / (r - l);
679 e11 = 2.0f / (t - b);
680 }
681
682 e03 = (l + r) / (l - r);
683 e13 = (t + b) / (b - t);
684
685 switch (range) {
686 case PROJ_NEG_POS :
687 e22 = 2.0f / (znear - zfar);
688 e23 = (znear + zfar) / (znear - zfar);
689 break;
690 case PROJ_NEG_ZERO :
691 e22 = 1.0f / (znear - zfar);
692 e23 = (znear + zfar) / (znear - zfar) * 0.5f - 0.5f;
693 e03 = -e03;
694 break;
695 case PROJ_ZERO_POS :
696 e22 = 2.0f / (znear - zfar);
697 e23 = znear / (znear - zfar);
698 break;
699 }
700 }
701
702 void frustum(ProjRange range, float l, float r, float b, float t, float znear, float zfar, bool rotate90 = false) {
703 identity();
704
705 if (rotate90) {
706 e00 = e11 = 0.0f;
707 e01 = 2.0f * znear / (r - l);
708 e10 = 2.0f * znear / (b - t);
709 } else {
710 e00 = 2.0f * znear / (r - l);
711 e11 = 2.0f * znear / (t - b);
712 }
713
714 e02 = (r + l) / (r - l);
715 e12 = (t + b) / (t - b);
716 e32 = -1.0f;
717 e33 = 0.0f;
718
719 switch (range) {
720 case PROJ_NEG_POS :
721 e22 = (znear + zfar) / (znear - zfar);
722 e23 = 2.0f * zfar * znear / (znear - zfar);
723 break;
724 case PROJ_NEG_ZERO :
725 e22 = znear / (znear - zfar);
726 e23 = zfar * znear / (znear - zfar);
727 break;
728 case PROJ_ZERO_POS :
729 e22 = zfar / (znear - zfar);
730 e23 = znear * e22;
731 break;
732 }
733 }
734
735 void perspective(ProjRange range, float fov, float aspect, float znear, float zfar, float eye = 0.0f, bool rotate90 = false) {
736 float y = tanf(fov * 0.5f * DEG2RAD) * znear;
737 float x = y;
738 float eyeX, eyeY;
739
740 if (rotate90) {
741 eyeX = 0.0f;
742 eyeY = -eye;
743 aspect = 1.0f / aspect;
744 swap(x, y);
745 } else {
746 eyeX = eye;
747 eyeY = 0.0f;
748 }
749
750 if (aspect >= 1.0f) {
751 x = y * aspect;
752 } else {
753 y /= aspect;
754 }
755
756 frustum(range, -x - eyeX, x - eyeX, -y - eyeY, y - eyeY, znear, zfar, rotate90);
757 }
758
viewportmat4759 void viewport(float x, float y, float width, float height, float n, float f) {
760 identity();
761 e00 = width * 0.5f;
762 e11 = height * 0.5f;
763 e22 = (f - n) * 0.5f;
764 e23 = (f + n) * 0.5f;
765 e03 = x + e00;
766 e13 = y + e11;
767 }
768
mat4mat4769 mat4(const vec3 &from, const vec3 &at, const vec3 &up) {
770 vec3 r, u, d;
771 d = (from - at).normal();
772 r = up.cross(d).normal();
773 u = d.cross(r);
774
775 this->right() = vec4(r, 0.0f);
776 this->up() = vec4(u, 0.0f);
777 this->dir() = vec4(d, 0.0f);
778 this->offset() = vec4(from, 1.0f);
779 }
780
mat4mat4781 mat4(const vec4 &reflectPlane) {
782 float a = reflectPlane.x,
783 b = reflectPlane.y,
784 c = reflectPlane.z,
785 d = reflectPlane.w;
786
787 right() = vec4(1 - 2*a*a, - 2*b*a, - 2*c*a, 0);
788 up() = vec4( - 2*a*b, 1 - 2*b*b, - 2*c*b, 0);
789 dir() = vec4( - 2*a*c, - 2*b*c, 1 - 2*c*c, 0);
790 offset() = vec4( - 2*a*d, - 2*b*d, - 2*c*d, 1);
791 }
792
793
identitymat4794 void identity() {
795 e10 = e20 = e30 = e01 = e21 = e31 = e02 = e12 = e32 = e03 = e13 = e23 = 0.0f;
796 e00 = e11 = e22 = e33 = 1.0f;
797 }
798
799 mat4 operator * (const mat4 &m) const {
800 mat4 r;
801 r.e00 = e00 * m.e00 + e01 * m.e10 + e02 * m.e20 + e03 * m.e30;
802 r.e10 = e10 * m.e00 + e11 * m.e10 + e12 * m.e20 + e13 * m.e30;
803 r.e20 = e20 * m.e00 + e21 * m.e10 + e22 * m.e20 + e23 * m.e30;
804 r.e30 = e30 * m.e00 + e31 * m.e10 + e32 * m.e20 + e33 * m.e30;
805 r.e01 = e00 * m.e01 + e01 * m.e11 + e02 * m.e21 + e03 * m.e31;
806 r.e11 = e10 * m.e01 + e11 * m.e11 + e12 * m.e21 + e13 * m.e31;
807 r.e21 = e20 * m.e01 + e21 * m.e11 + e22 * m.e21 + e23 * m.e31;
808 r.e31 = e30 * m.e01 + e31 * m.e11 + e32 * m.e21 + e33 * m.e31;
809 r.e02 = e00 * m.e02 + e01 * m.e12 + e02 * m.e22 + e03 * m.e32;
810 r.e12 = e10 * m.e02 + e11 * m.e12 + e12 * m.e22 + e13 * m.e32;
811 r.e22 = e20 * m.e02 + e21 * m.e12 + e22 * m.e22 + e23 * m.e32;
812 r.e32 = e30 * m.e02 + e31 * m.e12 + e32 * m.e22 + e33 * m.e32;
813 r.e03 = e00 * m.e03 + e01 * m.e13 + e02 * m.e23 + e03 * m.e33;
814 r.e13 = e10 * m.e03 + e11 * m.e13 + e12 * m.e23 + e13 * m.e33;
815 r.e23 = e20 * m.e03 + e21 * m.e13 + e22 * m.e23 + e23 * m.e33;
816 r.e33 = e30 * m.e03 + e31 * m.e13 + e32 * m.e23 + e33 * m.e33;
817 return r;
818 }
819
820 vec3 operator * (const vec3 &v) const {
821 return vec3(
822 e00 * v.x + e01 * v.y + e02 * v.z + e03,
823 e10 * v.x + e11 * v.y + e12 * v.z + e13,
824 e20 * v.x + e21 * v.y + e22 * v.z + e23);
825 }
826
827 vec4 operator * (const vec4 &v) const {
828 return vec4(
829 e00 * v.x + e01 * v.y + e02 * v.z + e03 * v.w,
830 e10 * v.x + e11 * v.y + e12 * v.z + e13 * v.w,
831 e20 * v.x + e21 * v.y + e22 * v.z + e23 * v.w,
832 e30 * v.x + e31 * v.y + e32 * v.z + e33 * v.w);
833 }
834
translatemat4835 void translate(const vec3 &offset) {
836 mat4 m;
837 m.identity();
838 m.setPos(offset);
839 *this = *this * m;
840 };
841
scalemat4842 void scale(const vec3 &factor) {
843 mat4 m;
844 m.identity();
845 m.e00 = factor.x;
846 m.e11 = factor.y;
847 m.e22 = factor.z;
848 *this = *this * m;
849 }
850
rotateXmat4851 void rotateX(float angle) {
852 mat4 m;
853 m.identity();
854 float s, c;
855 sincos(angle, &s, &c);
856 m.e11 = c; m.e21 = s;
857 m.e12 = -s; m.e22 = c;
858 *this = *this * m;
859 }
860
rotateYmat4861 void rotateY(float angle) {
862 mat4 m;
863 m.identity();
864 float s, c;
865 sincos(angle, &s, &c);
866 m.e00 = c; m.e20 = -s;
867 m.e02 = s; m.e22 = c;
868 *this = *this * m;
869 }
870
rotateZmat4871 void rotateZ(float angle) {
872 mat4 m;
873 m.identity();
874 float s, c;
875 sincos(angle, &s, &c);
876 m.e00 = c; m.e01 = -s;
877 m.e10 = s; m.e11 = c;
878 *this = *this * m;
879 }
880
rotateYXZmat4881 void rotateYXZ(const vec3 &angle) {
882 float s, c, a, b;
883
884 if (angle.y != 0.0f) {
885 sincos(angle.y, &s, &c);
886
887 a = e00 * c - e02 * s;
888 b = e02 * c + e00 * s;
889 e00 = a;
890 e02 = b;
891
892 a = e10 * c - e12 * s;
893 b = e12 * c + e10 * s;
894 e10 = a;
895 e12 = b;
896
897 a = e20 * c - e22 * s;
898 b = e22 * c + e20 * s;
899 e20 = a;
900 e22 = b;
901 }
902
903 if (angle.x != 0.0f) {
904 sincos(angle.x, &s, &c);
905
906 a = e01 * c + e02 * s;
907 b = e02 * c - e01 * s;
908 e01 = a;
909 e02 = b;
910
911 a = e11 * c + e12 * s;
912 b = e12 * c - e11 * s;
913 e11 = a;
914 e12 = b;
915
916 a = e21 * c + e22 * s;
917 b = e22 * c - e21 * s;
918 e21 = a;
919 e22 = b;
920 }
921
922 if (angle.z != 0.0f) {
923 sincos(angle.z, &s, &c);
924
925 a = e00 * c + e01 * s;
926 b = e01 * c - e00 * s;
927 e00 = a;
928 e01 = b;
929
930 a = e10 * c + e11 * s;
931 b = e11 * c - e10 * s;
932 e10 = a;
933 e11 = b;
934
935 a = e20 * c + e21 * s;
936 b = e21 * c - e20 * s;
937 e20 = a;
938 e21 = b;
939 }
940 }
941
lerpmat4942 void lerp(const mat4 &m, float t) {
943 e00 += (m.e00 - e00) * t;
944 e01 += (m.e01 - e01) * t;
945 e02 += (m.e02 - e02) * t;
946 e03 += (m.e03 - e03) * t;
947
948 e10 += (m.e10 - e10) * t;
949 e11 += (m.e11 - e11) * t;
950 e12 += (m.e12 - e12) * t;
951 e13 += (m.e13 - e13) * t;
952
953 e20 += (m.e20 - e20) * t;
954 e21 += (m.e21 - e21) * t;
955 e22 += (m.e22 - e22) * t;
956 e23 += (m.e23 - e23) * t;
957 }
958
detmat4959 float det() const {
960 return e00 * (e11 * (e22 * e33 - e32 * e23) - e21 * (e12 * e33 - e32 * e13) + e31 * (e12 * e23 - e22 * e13)) -
961 e10 * (e01 * (e22 * e33 - e32 * e23) - e21 * (e02 * e33 - e32 * e03) + e31 * (e02 * e23 - e22 * e03)) +
962 e20 * (e01 * (e12 * e33 - e32 * e13) - e11 * (e02 * e33 - e32 * e03) + e31 * (e02 * e13 - e12 * e03)) -
963 e30 * (e01 * (e12 * e23 - e22 * e13) - e11 * (e02 * e23 - e22 * e03) + e21 * (e02 * e13 - e12 * e03));
964 }
965
inversemat4966 mat4 inverse() const {
967 float idet = 1.0f / det();
968 mat4 r;
969 r.e00 = (e11 * (e22 * e33 - e32 * e23) - e21 * (e12 * e33 - e32 * e13) + e31 * (e12 * e23 - e22 * e13)) * idet;
970 r.e01 = -(e01 * (e22 * e33 - e32 * e23) - e21 * (e02 * e33 - e32 * e03) + e31 * (e02 * e23 - e22 * e03)) * idet;
971 r.e02 = (e01 * (e12 * e33 - e32 * e13) - e11 * (e02 * e33 - e32 * e03) + e31 * (e02 * e13 - e12 * e03)) * idet;
972 r.e03 = -(e01 * (e12 * e23 - e22 * e13) - e11 * (e02 * e23 - e22 * e03) + e21 * (e02 * e13 - e12 * e03)) * idet;
973 r.e10 = -(e10 * (e22 * e33 - e32 * e23) - e20 * (e12 * e33 - e32 * e13) + e30 * (e12 * e23 - e22 * e13)) * idet;
974 r.e11 = (e00 * (e22 * e33 - e32 * e23) - e20 * (e02 * e33 - e32 * e03) + e30 * (e02 * e23 - e22 * e03)) * idet;
975 r.e12 = -(e00 * (e12 * e33 - e32 * e13) - e10 * (e02 * e33 - e32 * e03) + e30 * (e02 * e13 - e12 * e03)) * idet;
976 r.e13 = (e00 * (e12 * e23 - e22 * e13) - e10 * (e02 * e23 - e22 * e03) + e20 * (e02 * e13 - e12 * e03)) * idet;
977 r.e20 = (e10 * (e21 * e33 - e31 * e23) - e20 * (e11 * e33 - e31 * e13) + e30 * (e11 * e23 - e21 * e13)) * idet;
978 r.e21 = -(e00 * (e21 * e33 - e31 * e23) - e20 * (e01 * e33 - e31 * e03) + e30 * (e01 * e23 - e21 * e03)) * idet;
979 r.e22 = (e00 * (e11 * e33 - e31 * e13) - e10 * (e01 * e33 - e31 * e03) + e30 * (e01 * e13 - e11 * e03)) * idet;
980 r.e23 = -(e00 * (e11 * e23 - e21 * e13) - e10 * (e01 * e23 - e21 * e03) + e20 * (e01 * e13 - e11 * e03)) * idet;
981 r.e30 = -(e10 * (e21 * e32 - e31 * e22) - e20 * (e11 * e32 - e31 * e12) + e30 * (e11 * e22 - e21 * e12)) * idet;
982 r.e31 = (e00 * (e21 * e32 - e31 * e22) - e20 * (e01 * e32 - e31 * e02) + e30 * (e01 * e22 - e21 * e02)) * idet;
983 r.e32 = -(e00 * (e11 * e32 - e31 * e12) - e10 * (e01 * e32 - e31 * e02) + e30 * (e01 * e12 - e11 * e02)) * idet;
984 r.e33 = (e00 * (e11 * e22 - e21 * e12) - e10 * (e01 * e22 - e21 * e02) + e20 * (e01 * e12 - e11 * e02)) * idet;
985 return r;
986 }
987
inverseOrthomat4988 mat4 inverseOrtho() const {
989 mat4 r;
990 r.e00 = e00; r.e10 = e01; r.e20 = e02; r.e30 = 0;
991 r.e01 = e10; r.e11 = e11; r.e21 = e12; r.e31 = 0;
992 r.e02 = e20; r.e12 = e21; r.e22 = e22; r.e32 = 0;
993 r.e03 = -(e03 * e00 + e13 * e10 + e23 * e20); // -dot(pos, right)
994 r.e13 = -(e03 * e01 + e13 * e11 + e23 * e21); // -dot(pos, up)
995 r.e23 = -(e03 * e02 + e13 * e12 + e23 * e22); // -dot(pos, dir)
996 r.e33 = 1;
997 return r;
998 }
999
transposemat41000 mat4 transpose() const {
1001 mat4 r;
1002 r.e00 = e00; r.e10 = e01; r.e20 = e02; r.e30 = e03;
1003 r.e01 = e10; r.e11 = e11; r.e21 = e12; r.e31 = e13;
1004 r.e02 = e20; r.e12 = e21; r.e22 = e22; r.e32 = e23;
1005 r.e03 = e30; r.e13 = e31; r.e23 = e32; r.e33 = e33;
1006 return r;
1007 }
1008
getRotmat41009 quat getRot() const {
1010 float t, s;
1011 t = 1.0f + e00 + e11 + e22;
1012 if (t > 0.0001f) {
1013 s = 0.5f / sqrtf(t);
1014 return quat((e21 - e12) * s, (e02 - e20) * s, (e10 - e01) * s, 0.25f / s);
1015 } else
1016 if (e00 > e11 && e00 > e22) {
1017 s = 0.5f / sqrtf(1.0f + e00 - e11 - e22);
1018 return quat(0.25f / s, (e01 + e10) * s, (e02 + e20) * s, (e21 - e12) * s);
1019 } else
1020 if (e11 > e22) {
1021 s = 0.5f / sqrtf(1.0f - e00 + e11 - e22);
1022 return quat((e01 + e10) * s, 0.25f / s, (e12 + e21) * s, (e02 - e20) * s);
1023 } else {
1024 s = 0.5f / sqrtf(1.0f - e00 - e11 + e22);
1025 return quat((e02 + e20) * s, (e12 + e21) * s, 0.25f / s, (e10 - e01) * s);
1026 }
1027 }
1028
setRotmat41029 void setRot(const quat &rot) {
1030 float sx = rot.x * rot.x,
1031 sy = rot.y * rot.y,
1032 sz = rot.z * rot.z,
1033 sw = rot.w * rot.w,
1034 inv = 1.0f / (sx + sy + sz + sw);
1035
1036 e00 = ( sx - sy - sz + sw) * inv;
1037 e11 = (-sx + sy - sz + sw) * inv;
1038 e22 = (-sx - sy + sz + sw) * inv;
1039 inv *= 2.0f;
1040
1041 float t1 = rot.x * rot.y;
1042 float t2 = rot.z * rot.w;
1043 e10 = (t1 + t2) * inv;
1044 e01 = (t1 - t2) * inv;
1045
1046 t1 = rot.x * rot.z;
1047 t2 = rot.y * rot.w;
1048 e20 = (t1 - t2) * inv;
1049 e02 = (t1 + t2) * inv;
1050
1051 t1 = rot.y * rot.z;
1052 t2 = rot.x * rot.w;
1053 e21 = (t1 + t2) * inv;
1054 e12 = (t1 - t2) * inv;
1055 }
1056
getPosmat41057 vec3 getPos() const {
1058 return offset().xyz();
1059 }
1060
setPosmat41061 void setPos(const vec3 &pos) {
1062 offset().xyz() = pos;
1063 }
1064 };
1065
1066 struct Basis {
1067 quat rot;
1068 vec3 pos;
1069 float w;
1070
BasisBasis1071 Basis() {}
BasisBasis1072 Basis(const quat &rot, const vec3 &pos) : rot(rot), pos(pos), w(1.0f) {}
BasisBasis1073 Basis(const mat4 &matrix) : rot(matrix.getRot()), pos(matrix.getPos()), w(1.0f) {}
1074
identityBasis1075 void identity() {
1076 rot = quat(0, 0, 0, 1);
1077 pos = vec3(0, 0, 0);
1078 w = 1.0f;
1079 }
1080
1081 Basis operator * (const Basis &basis) const {
1082 return Basis(rot * basis.rot, pos + rot * basis.pos);
1083 }
1084
1085 vec3 operator * (const vec3 &v) const {
1086 return rot * v + pos;
1087 }
1088
inverseBasis1089 Basis inverse() const {
1090 quat q = rot.conjugate();
1091 return Basis(q, -(q * pos));
1092 }
1093
translateBasis1094 void translate(const vec3 &v) {
1095 pos += rot * v;
1096 }
1097
rotateBasis1098 void rotate(const quat &q) {
1099 rot = rot * q;
1100 }
1101
lerpBasis1102 Basis lerp(const Basis &basis, float t) {
1103 if (t <= 0.0f) return *this;
1104 if (t >= 1.0f) return basis;
1105 Basis b;
1106 b.rot = rot.lerp(basis.rot, t);
1107 b.pos = pos.lerp(basis.pos, t);
1108 return b;
1109 }
1110 };
1111
1112 struct ubyte2 {
1113 uint8 x, y;
1114 };
1115
1116 union ubyte4 {
1117 struct { uint8 x, y, z, w; };
1118 uint32 value;
1119
ubyte4()1120 ubyte4() {}
ubyte4(uint8 x,uint8 y,uint8 z,uint8 w)1121 ubyte4(uint8 x, uint8 y, uint8 z, uint8 w) : x(x), y(y), z(z), w(w) {}
1122 };
1123
1124 struct short2 {
1125 int16 x, y;
1126
short2short21127 short2() {}
short2short21128 short2(int16 x, int16 y) : x(x), y(y) {}
1129
1130 inline bool operator == (const short2 &v) const { return x == v.x && y == v.y; }
1131 };
1132
1133 struct short3 {
1134 int16 x, y, z;
1135
short3short31136 short3() {}
short3short31137 short3(int16 x, int16 y, int16 z) : x(x), y(y), z(z) {}
1138
vec3short31139 operator vec3() const { return vec3((float)x, (float)y, (float)z); };
1140
1141 short3 operator + (const short3 &v) const { return short3(x + v.x, y + v.y, z + v.z); }
1142 short3 operator - (const short3 &v) const { return short3(x - v.x, y - v.y, z - v.z); }
1143 inline bool operator == (const short3 &v) const { return x == v.x && y == v.y && z == v.z; }
1144 };
1145
1146 struct short4 {
1147 int16 x, y, z, w;
1148
short4short41149 short4() {}
short4short41150 short4(int16 x, int16 y, int16 z, int16 w) : x(x), y(y), z(z), w(w) {}
1151
vec2short41152 operator vec2() const { return vec2((float)x, (float)y); };
vec3short41153 operator vec3() const { return vec3((float)x, (float)y, (float)z); };
vec4short41154 operator vec4() const { return vec4((float)x, (float)y, (float)z, (float)w); };
1155
short2short41156 operator short2() const { return *((short2*)this); }
short3short41157 operator short3() const { return *((short3*)this); }
1158
1159 inline bool operator == (const short4 &v) const { return x == v.x && y == v.y && z == v.z && w == v.w; }
1160 inline bool operator != (const short4 &v) const { return !(*this == v); }
1161
1162 inline int16& operator [] (int index) const { ASSERT(index >= 0 && index <= 3); return ((int16*)this)[index]; }
1163 };
1164
rotYXZ(const vec3 & angle)1165 quat rotYXZ(const vec3 &angle) {
1166 mat4 m;
1167 m.identity();
1168 m.rotateYXZ(angle);
1169 return m.getRot();
1170 }
1171
lerpAngle(const vec3 & a,const vec3 & b,float t)1172 quat lerpAngle(const vec3 &a, const vec3 &b, float t) { // TODO: optimization
1173
1174 return rotYXZ(a).lerp(rotYXZ(b), t);//.normal();
1175 }
1176
boxNormal(int x,int z)1177 vec3 boxNormal(int x, int z) {
1178 x %= 1024;
1179 z %= 1024;
1180
1181 if (x > 1024 - z)
1182 return x < z ? vec3(0, 0, 1) : vec3(1, 0, 0);
1183 else
1184 return x < z ? vec3(-1, 0, 0) : vec3(0, 0, -1);
1185 }
1186
1187
1188 struct Sphere {
1189 vec3 center;
1190 float radius;
1191
SphereSphere1192 Sphere() {}
SphereSphere1193 Sphere(const vec3 ¢er, float radius) : center(center), radius(radius) {}
1194
intersectSphere1195 bool intersect(const Sphere &s) const {
1196 float d = (center - s.center).length2();
1197 float r = (radius + s.radius);
1198 return d < r * r;
1199 }
1200
intersectSphere1201 bool intersect(const vec3 &rayPos, const vec3 &rayDir, float &t) const {
1202 vec3 v = rayPos - center;
1203 float h = -v.dot(rayDir);
1204 float d = h * h + radius * radius - v.length2();
1205
1206 if (d > 0.0f) {
1207 d = sqrtf(d);
1208 float tMin = h - d;
1209 float tMax = h + d;
1210 if (tMax > 0.0f) {
1211 if (tMin < 0.0f)
1212 tMin = 0.0f;
1213 t = tMin;
1214 return true;
1215 }
1216 }
1217 return false;
1218 }
1219 };
1220
1221
1222 struct Box {
1223 vec3 min, max;
1224
BoxBox1225 Box() {}
BoxBox1226 Box(const vec3 &min, const vec3 &max) : min(min), max(max) {}
1227
1228 vec3 operator [] (int index) const {
1229 ASSERT(index >= 0 && index <= 7);
1230 switch (index) {
1231 case 0 : return min;
1232 case 1 : return max;
1233 case 2 : return vec3(min.x, max.y, max.z);
1234 case 3 : return vec3(max.x, min.y, max.z);
1235 case 4 : return vec3(min.x, min.y, max.z);
1236 case 5 : return vec3(max.x, max.y, min.z);
1237 case 6 : return vec3(min.x, max.y, min.z);
1238 case 7 : return vec3(max.x, min.y, min.z);
1239 }
1240 return min;
1241 }
1242
intersection2DBox1243 Box intersection2D(const Box &b) const {
1244 Box r(vec3(0.0f), vec3(0.0f));
1245 if (max.x < b.min.x || min.x > b.max.x) return r;
1246 if (max.y < b.min.y || min.y > b.max.y) return r;
1247 r.max.x = ::min(max.x, b.max.x);
1248 r.max.y = ::min(max.y, b.max.y);
1249 r.min.x = ::max(min.x, b.min.x);
1250 r.min.y = ::max(min.y, b.min.y);
1251 return r;
1252 }
1253
1254 Box& operator += (const Box &box) {
1255 min.x = ::min(min.x, box.min.x);
1256 min.y = ::min(min.y, box.min.y);
1257 min.z = ::min(min.z, box.min.z);
1258 max.x = ::max(max.x, box.max.x);
1259 max.y = ::max(max.y, box.max.y);
1260 max.z = ::max(max.z, box.max.z);
1261 return *this;
1262 }
1263
1264 Box& operator += (const vec3 &v) {
1265 min.x = ::min(min.x, v.x);
1266 min.y = ::min(min.y, v.y);
1267 min.z = ::min(min.z, v.z);
1268 max.x = ::max(max.x, v.x);
1269 max.y = ::max(max.y, v.y);
1270 max.z = ::max(max.z, v.z);
1271 return *this;
1272 }
1273
1274 Box& operator -= (const Box &box) {
1275 min.x = ::max(min.x, box.min.x);
1276 min.y = ::max(min.y, box.min.y);
1277 min.z = ::max(min.z, box.min.z);
1278 max.x = ::min(max.x, box.max.x);
1279 max.y = ::min(max.y, box.max.y);
1280 max.z = ::min(max.z, box.max.z);
1281 return *this;
1282 }
1283
1284 Box operator * (const mat4 &m) const {
1285 Box res(vec3(+INF), vec3(-INF));
1286 for (int i = 0; i < 8; i++) {
1287 vec4 v = m * vec4((*this)[i], 1.0f);
1288 res += v.xyz() /= v.w;
1289 }
1290 return res;
1291 }
1292
centerBox1293 vec3 center() const {
1294 return (min + max) * 0.5f;
1295 }
1296
sizeBox1297 vec3 size() const {
1298 return max - min;
1299 }
1300
expandBox1301 void expand(const vec3 &v) {
1302 min -= v;
1303 max += v;
1304 }
1305
rotate90Box1306 void rotate90(int n) {
1307 switch (n) {
1308 case 0 : break;
1309 case 1 : *this = Box(vec3( min.z, min.y, -max.x), vec3( max.z, max.y, -min.x)); break;
1310 case 2 : *this = Box(vec3(-max.x, min.y, -max.z), vec3(-min.x, max.y, -min.z)); break;
1311 case 3 : *this = Box(vec3(-max.z, min.y, min.x), vec3(-min.z, max.y, max.x)); break;
1312 default : ASSERT(false);
1313 }
1314 }
1315
translateBox1316 void translate(const vec3 &offset) {
1317 min += offset;
1318 max += offset;
1319 }
1320
closestPointBox1321 vec3 closestPoint(const vec3 &p) const {
1322 return vec3(clamp(p.x, min.x, max.x),
1323 clamp(p.y, min.y, max.y),
1324 clamp(p.z, min.z, max.z));
1325 }
1326
containsBox1327 bool contains(const vec3 &v) const {
1328 return v.x >= min.x && v.x <= max.x && v.y >= min.y && v.y <= max.y && v.z >= min.z && v.z <= max.z;
1329 }
1330
pushOut2DBox1331 vec3 pushOut2D(const vec3 &v) const {
1332 float ax = v.x - min.x;
1333 float bx = max.x - v.x;
1334 float az = v.z - min.z;
1335 float bz = max.z - v.z;
1336
1337 vec3 p = vec3(0.0f);
1338 if (ax <= bx && ax <= az && ax <= bz)
1339 p.x = -ax;
1340 else if (bx <= ax && bx <= az && bx <= bz)
1341 p.x = bx;
1342 else if (az <= ax && az <= bx && az <= bz)
1343 p.z = -az;
1344 else
1345 p.z = bz;
1346
1347 return p;
1348 }
1349
pushOut2DBox1350 vec3 pushOut2D(const Box &b) const {
1351 float ax = b.max.x - min.x;
1352 float bx = max.x - b.min.x;
1353 float az = b.max.z - min.z;
1354 float bz = max.z - b.min.z;
1355
1356 vec3 p = vec3(0.0f);
1357 if (ax <= bx && ax <= az && ax <= bz)
1358 p.x -= ax;
1359 else if (bx <= ax && bx <= az && bx <= bz)
1360 p.x += bx;
1361 else if (az <= ax && az <= bx && az <= bz)
1362 p.z -= az;
1363 else
1364 p.z += bz;
1365
1366 return p;
1367 }
1368
intersectBox1369 bool intersect(const Box &box) const {
1370 return !((max.x < box.min.x || min.x > box.max.x) || (max.y < box.min.y || min.y > box.max.y) || (max.z < box.min.z || min.z > box.max.z));
1371 }
1372
intersectBox1373 bool intersect(const Sphere &sphere) const {
1374 if (contains(sphere.center))
1375 return true;
1376 vec3 dir = sphere.center - closestPoint(sphere.center);
1377 return (dir.length2() < sphere.radius * sphere.radius);
1378 }
1379
intersectBox1380 bool intersect(const vec3 &rayPos, const vec3 &rayDir, float &t) const {
1381 float tMax = INF, tMin = -tMax;
1382
1383 for (int i = 0; i < 3; i++)
1384 if (rayDir[i] != 0) {
1385 float lo = (min[i] - rayPos[i]) / rayDir[i];
1386 float hi = (max[i] - rayPos[i]) / rayDir[i];
1387 tMin = ::max(tMin, ::min(lo, hi));
1388 tMax = ::min(tMax, ::max(lo, hi));
1389 } else
1390 if (rayPos[i] < min[i] || rayPos[i] > max[i])
1391 return false;
1392 t = tMin;
1393 return (tMin <= tMax) && (tMax > 0.0f);
1394 }
1395
intersectBox1396 bool intersect(const mat4 &matrix, const vec3 &rayPos, const vec3 &rayDir, float &t) const {
1397 mat4 mInv = matrix.inverseOrtho();
1398 return intersect(mInv * rayPos, (mInv * vec4(rayDir, 0)).xyz(), t);
1399 }
1400 };
1401
1402 union Color32 { // RGBA8888
1403 uint32 value;
1404 struct { uint8 r, g, b, a; };
1405
Color32()1406 Color32() {}
Color32(uint32 value)1407 Color32(uint32 value) : value(value) {}
Color32(uint8 r,uint8 g,uint8 b,uint8 a)1408 Color32(uint8 r, uint8 g, uint8 b, uint8 a) : r(r), g(g), b(b), a(a) {}
1409
SetRGB15(uint16 v)1410 void SetRGB15(uint16 v) {
1411 r = (v & 0x7C00) >> 7;
1412 g = (v & 0x03E0) >> 2;
1413 b = (v & 0x001F) << 3;
1414 a = 255;
1415 }
1416
YCbCr_T871_420(int32 Y0,int32 Y1,int32 Y2,int32 Y3,int32 Cb,int32 Cr,int32 F,Color32 & C0,Color32 & C1,Color32 & C2,Color32 & C3)1417 static void YCbCr_T871_420(int32 Y0, int32 Y1, int32 Y2, int32 Y3, int32 Cb, int32 Cr, int32 F, Color32 &C0, Color32 &C1, Color32 &C2, Color32 &C3) {
1418 static const uint32 dither[8] = {
1419 0x00000600, 0x00060006, 0x00040204, 0x00020402,
1420 0x00000000, 0x00000000, 0x00000000, 0x00000000,
1421 };
1422
1423 ASSERT(F == 0 || F == 4);
1424
1425 int32 R = ( 91881 * Cr ) >> 16;
1426 int32 G = ( 22550 * Cb + 46799 * Cr ) >> 16;
1427 int32 B = ( 116129 * Cb ) >> 16;
1428
1429 const Color32 *d = (Color32*)dither + F;
1430
1431 C0.r = clamp(Y0 + R + d->r, 0, 255);
1432 C0.g = clamp(Y0 - G + d->g, 0, 255);
1433 C0.b = clamp(Y0 + B + d->b, 0, 255);
1434 C0.a = 255;
1435 d++;
1436
1437 C1.r = clamp(Y1 + R + d->r, 0, 255);
1438 C1.g = clamp(Y1 - G + d->g, 0, 255);
1439 C1.b = clamp(Y1 + B + d->b, 0, 255);
1440 C1.a = 255;
1441 d++;
1442
1443 C2.r = clamp(Y2 + R + d->r, 0, 255);
1444 C2.g = clamp(Y2 - G + d->g, 0, 255);
1445 C2.b = clamp(Y2 + B + d->b, 0, 255);
1446 C2.a = 255;
1447 d++;
1448
1449 C3.r = clamp(Y3 + R + d->r, 0, 255);
1450 C3.g = clamp(Y3 - G + d->g, 0, 255);
1451 C3.b = clamp(Y3 + B + d->b, 0, 255);
1452 C3.a = 255;
1453 }
1454 };
1455
1456 struct Color24 { // RGB888
1457 uint8 r, g, b;
1458
Color24Color241459 Color24() {}
Color24Color241460 Color24(uint8 r, uint8 g, uint8 b) : r(r), g(g), b(b) {}
1461
Color32Color241462 operator Color32() const { return Color32(r, g, b, 255); }
1463 };
1464
1465 union Color16 { // RGBA5551
1466 struct { uint16 b:5, g:5, r:5, a:1; };
1467 uint16 value;
1468
Color16()1469 Color16() {}
Color16(uint16 value)1470 Color16(uint16 value) : value(value) {}
1471
Color24()1472 operator Color24() const { return Color24((r << 3) | (r >> 2), (g << 3) | (g >> 2), (b << 3) | (b >> 2)); }
Color32()1473 operator Color32() const { return Color32((r << 3) | (r >> 2), (g << 3) | (g >> 2), (b << 3) | (b >> 2), -a); }
1474 };
1475
1476 union ColorCLUT { // RGBA5551
1477 struct { uint16 r:5, g:5, b:5, a:1; };
1478 uint16 value;
1479
ColorCLUT()1480 ColorCLUT() {}
ColorCLUT(uint16 value)1481 ColorCLUT(uint16 value) : value(value) {}
1482
Color24()1483 operator Color24() const { return Color24((r << 3) | (r >> 2), (g << 3) | (g >> 2), (b << 3) | (b >> 2)); }
Color32()1484 operator Color32() const { return Color32((r << 3) | (r >> 2), (g << 3) | (g >> 2), (b << 3) | (b >> 2), -a); }
1485 };
1486
1487
1488 struct ColorIndex4 {
1489 uint8 a:4, b:4;
1490 };
1491
1492 struct Tile4 {
1493 ColorIndex4 index[256 * 256 / 2];
1494 };
1495
1496 struct Tile8 {
1497 uint8 index[256 * 256];
1498 };
1499
1500 struct Tile16 {
1501 Color16 color[256 * 256];
1502 };
1503
1504 #ifdef USE_ATLAS_RGBA16
1505 union AtlasColor {
1506 struct { uint16 a:1, b:5, g:5, r:5; };
1507 uint16 value;
1508
AtlasColor()1509 AtlasColor() {}
AtlasColor(uint16 value)1510 AtlasColor(uint16 value) : value(value) {}
AtlasColor(const Color16 & value)1511 AtlasColor(const Color16 &value) : a(value.a), b(value.b), g(value.g), r(value.r) {}
AtlasColor(const Color24 & value)1512 AtlasColor(const Color24 &value) : a(1), b(value.b >> 3), g(value.g >> 3), r(value.r >> 3) {}
AtlasColor(const Color32 & value)1513 AtlasColor(const Color32 &value) : a(value.a ? 1 : 0), b(value.b >> 3), g(value.g >> 3), r(value.r >> 3) {}
AtlasColor(const ColorCLUT & value)1514 AtlasColor(const ColorCLUT &value) : a(value.a), b(value.b), g(value.g), r(value.r) {}
1515 };
1516
1517 #define ATLAS_FORMAT FMT_RGBA16
1518 #else
1519 typedef Color32 AtlasColor;
1520 #define ATLAS_FORMAT FMT_RGBA
1521 #endif
1522
1523 struct AtlasTile {
1524 AtlasColor color[256 * 256];
1525 };
1526
1527 struct Tile32 {
1528 Color32 color[256 * 256];
1529 };
1530
1531 struct CLUT {
1532 ColorCLUT color[16];
1533 };
1534
1535 namespace StrUtils {
1536
toLower(char * str)1537 void toLower(char *str) {
1538 if (!str) return;
1539
1540 while (char &c = *str++) {
1541 if (c >= 'A' && c <= 'Z')
1542 c -= 'Z' - 'z';
1543 }
1544 }
1545
copy(const char * str)1546 char* copy(const char *str) {
1547 if (str == NULL) {
1548 return NULL;
1549 }
1550 char *res = new char[strlen(str) + 1];
1551 strcpy(res, str);
1552 return res;
1553 }
1554
length(uint16 * str)1555 int32 length(uint16 *str) {
1556 if (!str || !str[0]) return 0;
1557 int32 len = 0;
1558 while (*str++) {
1559 len++;
1560 }
1561 return len;
1562 }
1563 }
1564
1565
1566 template <typename T>
1567 struct Array {
1568 int capacity;
1569 int length;
1570 T *items;
1571
capacityArray1572 Array(int capacity = 32) : capacity(capacity), length(0), items(NULL) {}
1573
~ArrayArray1574 ~Array() {
1575 clear();
1576 }
1577
reserveArray1578 void reserve(int capacity) {
1579 this->capacity = capacity;
1580 if (items)
1581 items = (T*)realloc(items, capacity * sizeof(T));
1582 else
1583 items = (T*)malloc(capacity * sizeof(T));
1584 }
1585
pushArray1586 int push(const T &item) {
1587 if (!items)
1588 items = (T*)malloc(capacity * sizeof(T));
1589
1590 if (length == capacity)
1591 reserve(capacity + capacity / 2);
1592
1593 items[length] = item;
1594 return length++;
1595 }
1596
popArray1597 int pop() {
1598 ASSERT(length > 0);
1599 return --length;
1600 }
1601
removeFastArray1602 void removeFast(int index) {
1603 (*this)[index] = (*this)[length - 1];
1604 length--;
1605 }
1606
removeArray1607 void remove(int index) {
1608 length--;
1609 ASSERT(length >= 0);
1610 for (int i = index; i < length; i++)
1611 items[i] = items[i + 1];
1612 }
1613
resizeArray1614 void resize(int length) {
1615 if (capacity < length)
1616 reserve(length);
1617 this->length = length;
1618 }
1619
resetArray1620 void reset() {
1621 length = 0;
1622 }
1623
clearArray1624 void clear() {
1625 reset();
1626 free(items);
1627 items = NULL;
1628 }
1629
findArray1630 int find(const T &item) {
1631 for (int i = 0; i < length; i++) {
1632 if (items[i] == item)
1633 return i;
1634 }
1635 return -1;
1636 }
1637
sortArray1638 void sort() {
1639 ::sort(items, length);
1640 }
1641
1642 T& operator[] (int index) {
1643 ASSERT(index >= 0 && index < length);
1644 return items[index];
1645 };
1646 };
1647
1648
1649 struct Stream;
1650
1651 extern void osCacheWrite (Stream *stream);
1652 extern void osCacheRead (Stream *stream);
1653
1654 extern void osReadSlot (Stream *stream);
1655 extern void osWriteSlot (Stream *stream);
1656
1657 #ifdef _OS_WEB
1658 extern void osDownload (Stream *stream);
1659 #endif
1660
1661 char cacheDir[255];
1662 char saveDir[255];
1663 char contentDir[255];
1664
1665 #define STREAM_BUFFER_SIZE (16 * 1024)
1666
1667 #define MAX_PACKS 32
1668
1669 struct Stream {
1670 typedef void (Callback)(Stream *stream, void *userData);
1671 Callback *callback;
1672 void *userData;
1673
1674 FILE *f;
1675 char *data;
1676 char *name;
1677 int size, pos, fpos;
1678
1679 char *buffer;
1680 int bufferIndex;
1681 bool buffering;
1682 uint32 baseOffset;
1683
1684 struct Pack
1685 {
1686 Stream* stream;
1687 uint8* table;
1688 uint32 count;
1689
1690 struct FileInfo
1691 {
1692 uint32 size;
1693 uint32 offset;
1694 };
1695
findFileStream::Pack1696 bool findFile(const char* name, FileInfo &info)
1697 {
1698 if (!table || !name || !name[0]) {
1699 return false;
1700 }
1701
1702 uint16 len = (uint16)strlen(name);
1703 uint8* ptr = table;
1704
1705 for (uint32 i = 0; i < count; i++)
1706 {
1707 uint32 magic;
1708 memcpy(&magic, ptr, sizeof(magic));
1709 if (magic != 0x02014B50) {
1710 ASSERT(false);
1711 return false;
1712 }
1713
1714 uint16 nameLen, extraLen, infoLen;
1715 memcpy(&nameLen, ptr + 28, sizeof(nameLen));
1716 memcpy(&extraLen, ptr + 30, sizeof(extraLen));
1717
1718 if ((nameLen == len) && (memcmp(ptr + 46, name, len) == 0))
1719 {
1720 uint16 compression;
1721 memcpy(&compression, ptr + 10, sizeof(compression));
1722
1723 if (compression != 0)
1724 {
1725 ASSERT(false);
1726 return false;
1727 }
1728
1729 memcpy(&info.size, ptr + 24, sizeof(info.size));
1730 memcpy(&info.offset, ptr + 42, sizeof(info.offset));
1731
1732 stream->setPos(info.offset);
1733 magic = stream->readLE32();
1734
1735 if (magic != 0x04034B50) {
1736 ASSERT(false);
1737 return false;
1738 }
1739 stream->seek(22);
1740 nameLen = stream->readLE16();
1741 extraLen = stream->readLE16();
1742
1743 info.offset += 4 + 22 + 2 + 2 + nameLen + extraLen;
1744
1745 return true;
1746 }
1747
1748 memcpy(&infoLen, ptr + 32, sizeof(infoLen));
1749
1750 ptr += 46 + nameLen + extraLen + infoLen;
1751 }
1752
1753 return false;
1754 }
1755
PackStream::Pack1756 Pack(const char *name) : stream(NULL), table(NULL), count(0)
1757 {
1758 stream = new Stream(name);
1759 stream->buffering = false;
1760 stream->setPos(stream->size - 22);
1761 uint32 magic = stream->readLE32();
1762
1763 if (magic != 0x06054B50)
1764 {
1765 ASSERT(false);
1766 return;
1767 }
1768
1769 stream->seek(6);
1770 count = stream->readLE16();
1771 uint32 tableSize = stream->readLE32();
1772 uint32 tableOffset = stream->readLE32();
1773
1774 stream->setPos(tableOffset);
1775
1776 table = new uint8[tableSize];
1777 stream->raw(table, tableSize);
1778 }
1779
~PackStream::Pack1780 ~Pack() {
1781 delete stream;
1782 delete[] table;
1783 }
1784 };
1785
1786 static Pack* packs[MAX_PACKS];
1787
1788 static Array<char*> fileList;
1789
addPackStream1790 static bool addPack(const char *name)
1791 {
1792 if (!existsContent(name)) {
1793 return false;
1794 }
1795
1796 for (int i = 0; i < MAX_PACKS; i++)
1797 {
1798 if (!packs[i])
1799 {
1800 packs[i] = new Pack(name);
1801 return true;
1802 }
1803 }
1804 return false;
1805 }
1806
initStream1807 static void init() {
1808 readFileList();
1809 }
1810
deinitStream1811 static void deinit()
1812 {
1813 for (int i = 0; i < MAX_PACKS; i++)
1814 {
1815 if (!packs[i]) break;
1816 delete packs[i];
1817 }
1818
1819 for (int i = 0; i < fileList.length; i++) {
1820 delete[] fileList[i];
1821 }
1822 fileList.clear();
1823 }
1824
1825 private:
1826 #ifdef _OS_3DS
streamThreadStream1827 static void streamThread(void *arg) {
1828 Stream* stream = (Stream*)arg;
1829 stream->openFile();
1830 }
1831 #endif
1832
openFileStream1833 void openFile() {
1834 char path[255];
1835
1836 path[0] = 0;
1837 if (contentDir[0] && (!cacheDir[0] || !strstr(name, cacheDir))) {
1838 strcpy(path, contentDir);
1839 }
1840 strcat(path, name);
1841 fixBackslash(path);
1842
1843 f = fopen(path, "rb");
1844
1845 if (!f) {
1846 #ifdef _OS_WEB
1847 osDownload(this);
1848 #else
1849 LOG("error loading file \"%s\"\n", name);
1850 if (callback) {
1851 callback(NULL, userData);
1852 delete this;
1853 } else {
1854 ASSERT(false);
1855 }
1856 #endif
1857 } else {
1858 fseek(f, 0, SEEK_END);
1859 size = (int32)ftell(f);
1860 fseek(f, 0, SEEK_SET);
1861
1862 fpos = 0;
1863 bufferIndex = -1;
1864
1865 if (callback) callback(this, userData);
1866 }
1867 }
1868 public:
1869
callbackStream1870 Stream(const char *name, const void *data, int size, Callback *callback = NULL, void *userData = NULL) : callback(callback), userData(userData), f(NULL), data((char*)data), name(NULL), size(size), pos(0), buffer(NULL) {
1871 this->name = StrUtils::copy(name);
1872 }
1873
callbackStream1874 Stream(const char *name, Callback *callback = NULL, void *userData = NULL) : callback(callback), userData(userData), f(NULL), data(NULL), name(NULL), size(-1), pos(0), buffer(NULL), buffering(true), baseOffset(0) {
1875 if (!name && callback) {
1876 callback(NULL, userData);
1877 delete this;
1878 return;
1879 }
1880
1881 if (!name) {
1882 ASSERT(false);
1883 }
1884
1885 Stream::Pack::FileInfo info;
1886
1887 char path[256];
1888
1889 for (int i = 0; i < MAX_PACKS; i++)
1890 {
1891 if (!packs[i]) break;
1892
1893 if (packs[i]->findFile(name, info))
1894 {
1895 path[0] = 0;
1896 if (contentDir[0] && (!cacheDir[0] || !strstr(name, cacheDir))) {
1897 strcpy(path, contentDir);
1898 }
1899 strcat(path, packs[i]->stream->name);
1900 fixBackslash(path);
1901
1902 f = fopen(path, "rb");
1903 if (!f) {
1904 LOG("error loading file from pack \"%s -> %s\"\n", packs[i]->stream->name, name);
1905 ASSERT(false);
1906 return;
1907 }
1908 baseOffset = info.offset;
1909 fseek(f, info.offset, SEEK_SET);
1910 size = info.size;
1911
1912 fpos = 0;
1913 bufferIndex = -1;
1914
1915 this->name = StrUtils::copy(name);
1916 if (callback) callback(this, userData);
1917 return;
1918 }
1919 }
1920
1921 this->name = StrUtils::copy(name);
1922
1923 #ifdef _OS_3DS /* TODO
1924 if (callback) {
1925 s32 priority = 0;
1926 svcGetThreadPriority(&priority, CUR_THREAD_HANDLE);
1927 threadCreate(streamThread, this, 64 * 1024, priority - 1, -2, false);
1928 return;
1929 }*/
1930 #endif
1931
1932 openFile();
1933 }
1934
~StreamStream1935 ~Stream() {
1936 delete[] name;
1937 delete[] buffer;
1938 if (f) fclose(f);
1939 }
1940
1941 #if _OS_3DS
readDirectoryStream1942 static void readDirectory(const FS_Archive &archive, const char* path) {
1943 char buf[255];
1944 strcpy(buf, contentDir + 5); // 5 to skip "sdmc:"
1945 strcat(buf, path);
1946
1947 FS_Path fsPath = fsMakePath(FS_PathType::PATH_ASCII, buf);
1948
1949 Handle dir;
1950 if (FSUSER_OpenDirectory(&dir, archive, fsPath) != 0) {
1951 return;
1952 }
1953
1954 int32 pathLen = strlen(path);
1955 strcpy(buf, path);
1956
1957 while (1) {
1958 FS_DirectoryEntry entry;
1959
1960 u32 entriesRead = 0;
1961 FSDIR_Read(dir, &entriesRead, 1, &entry);
1962
1963 if (entriesRead == 0) {
1964 break;
1965 }
1966
1967 int32 len = utf16_to_utf8((uint8*)buf + pathLen, entry.name, StrUtils::length(entry.name));
1968 buf[pathLen + len] = 0;
1969
1970 if (entry.attributes & FS_ATTRIBUTE_DIRECTORY) {
1971 strcat(buf, "/");
1972 readDirectory(archive, buf);
1973 } else {
1974 fileList.push(StrUtils::copy(buf));
1975 }
1976 }
1977
1978 FSDIR_Close(dir);
1979 }
1980
readFileListStream1981 static void readFileList() {
1982 FS_Archive sdmc;
1983 FS_Path fsRoot = fsMakePath(FS_PathType::PATH_ASCII, "");
1984
1985 if (FSUSER_OpenArchive(&sdmc, FS_ArchiveID::ARCHIVE_SDMC, fsRoot) != 0) {
1986 return;
1987 }
1988
1989 readDirectory(sdmc, "");
1990
1991 FSUSER_CloseArchive(sdmc);
1992 }
1993 #elif _OS_PSV
readDirectoryStream1994 static void readDirectory(char* path) {
1995 SceUID dd = sceIoDopen(path);
1996
1997 size_t len = strlen(path);
1998
1999 SceIoDirent entry;
2000 while (sceIoDread(dd, &entry) > 0)
2001 {
2002 strcat(path, entry.d_name);
2003
2004 if (SCE_S_ISDIR(entry.d_stat.st_mode))
2005 {
2006 strcat(path, "/");
2007 readDirectory(path);
2008 } else {
2009 fileList.push(StrUtils::copy(path + strlen(contentDir)));
2010 }
2011
2012 path[len] = 0;
2013 }
2014
2015 sceIoClose(dd);
2016 }
2017
readFileListStream2018 static void readFileList() {
2019 char path[255];
2020 strcpy(path, contentDir);
2021 readDirectory(path);
2022 }
2023 #else
readFileListStream2024 static void readFileList() {};
2025 #endif
2026
2027 static void cacheRead(const char *name, Callback *callback = NULL, void *userData = NULL) {
2028 Stream *stream = new Stream(name, NULL, 0, callback, userData);
2029 #ifdef _OS_ANDROID // use saveDir for settings on android devices
2030 if (name && strcmp(name, "settings") == 0) {
2031 osReadSlot(stream);
2032 return;
2033 }
2034 #endif
2035 osCacheRead(stream);
2036 }
2037
2038 static void cacheWrite(const char *name, const char *data, int size, Callback *callback = NULL, void *userData = NULL) {
2039 Stream *stream = new Stream(name, data, size, callback, userData);
2040 #ifdef _OS_ANDROID // use saveDir for settings on android devices
2041 if (name && strcmp(name, "settings") == 0) {
2042 osWriteSlot(stream);
2043 return;
2044 }
2045 #endif
2046 osCacheWrite(stream);
2047 }
2048
fixBackslashStream2049 static void fixBackslash(char *str) {
2050 #ifdef _OS_XBOX
2051 int len = strlen(str);
2052 for (int i = 0; i < len; i++) {
2053 if (str[i] == '/') {
2054 str[i] = '\\';
2055 }
2056 }
2057 #endif
2058 }
2059
existsStream2060 static bool exists(const char *name) {
2061 FILE *f = fopen(name, "rb");
2062 if (!f) return false;
2063 fclose(f);
2064 return true;
2065 }
2066
existsContentStream2067 static bool existsContent(const char *name) {
2068 for (uint32 i = 0; i < MAX_PACKS; i++)
2069 {
2070 if (!packs[i]) break;
2071
2072 Pack::FileInfo info;
2073 if (packs[i]->findFile(name, info))
2074 return true;
2075 }
2076
2077 if (fileList.length) {
2078 for (int i = 0; i < fileList.length; i++) {
2079 if (strcmp(fileList[i], name) == 0) {
2080 return true;
2081 }
2082 }
2083 return false;
2084 }
2085
2086 char fileName[1024];
2087 strcpy(fileName, contentDir);
2088 strcat(fileName, name);
2089 fixBackslash(fileName);
2090 return exists(fileName);
2091 }
2092
setPosStream2093 void setPos(int pos) {
2094 this->pos = pos;
2095 }
2096
seekStream2097 void seek(int offset) {
2098 pos += offset;
2099 }
2100
rawStream2101 void raw(void *data, int count) {
2102 if (!count) return;
2103
2104 if (f) {
2105
2106 if (!buffering) {
2107 if (fpos != pos) {
2108 fseek(f, baseOffset + pos, SEEK_SET);
2109 fpos = pos;
2110 }
2111 fread(data, 1, count, f);
2112 pos += count;
2113 fpos += count;
2114 return;
2115 }
2116
2117 uint8 *ptr = (uint8*)data;
2118
2119 while (count > 0) {
2120 int bIndex = pos / STREAM_BUFFER_SIZE;
2121
2122 if (bufferIndex != bIndex) {
2123 bufferIndex = bIndex;
2124
2125 int readed;
2126 int part;
2127
2128 if (fpos == pos) {
2129 part = min(count / STREAM_BUFFER_SIZE * STREAM_BUFFER_SIZE, size - fpos);
2130 if (part > STREAM_BUFFER_SIZE) {
2131 readed = (int)fread(ptr, 1, part, f);
2132
2133 #ifdef TEST_SLOW_FIO
2134 LOG("%s read %d + %d\n", name, fpos, readed);
2135 Sleep(5);
2136 #endif
2137
2138 ASSERT(part == readed);
2139 count -= readed;
2140 fpos += readed;
2141 pos += readed;
2142 ptr += readed;
2143
2144 if (count <= 0) {
2145 bufferIndex = -1;
2146 break;
2147 }
2148
2149 bufferIndex = pos / STREAM_BUFFER_SIZE;
2150 }
2151 }
2152
2153 if (fpos != bufferIndex * STREAM_BUFFER_SIZE) {
2154 fpos = bufferIndex * STREAM_BUFFER_SIZE;
2155 fseek(f, baseOffset + fpos, SEEK_SET);
2156
2157 #ifdef TEST_SLOW_FIO
2158 LOG("%s seek %d\n", name, fpos);
2159 Sleep(5);
2160 #endif
2161 }
2162
2163 if (!buffer) {
2164 buffer = new char[STREAM_BUFFER_SIZE];
2165 }
2166
2167 part = min(STREAM_BUFFER_SIZE, size - fpos);
2168 readed = (int)fread(buffer, 1, part, f);
2169
2170 #ifdef TEST_SLOW_FIO
2171 LOG("%s read %d + %d\n", name, fpos, readed);
2172 Sleep(5);
2173 #endif
2174
2175 ASSERT(part == readed);
2176 fpos += readed;
2177 }
2178
2179 ASSERT(buffer);
2180
2181 int bPos = pos % STREAM_BUFFER_SIZE;
2182 int delta = min(STREAM_BUFFER_SIZE - bPos, count);
2183
2184 memcpy(ptr, buffer + bPos, delta);
2185 count -= delta;
2186 pos += delta;
2187 ptr += delta;
2188 }
2189 } else {
2190 memcpy(data, this->data + pos, count);
2191 pos += count;
2192 }
2193 }
2194
2195 template <typename T>
readStream2196 inline T& read(T &x) {
2197 raw(&x, sizeof(x));
2198 return x;
2199 }
2200
2201 template <typename T>
readStream2202 inline T* read(T *&a, int count) {
2203 if (count) {
2204 a = new T[count];
2205 raw(a, count * sizeof(T));
2206 } else
2207 a = NULL;
2208 return a;
2209 }
2210
readStream2211 inline uint8 read() {
2212 uint8 x;
2213 return read(x);
2214 }
2215
readLE16Stream2216 inline uint16 readLE16() {
2217 uint16 x;
2218 return read(x);
2219 }
2220
readLE32Stream2221 inline uint32 readLE32() {
2222 uint32 x;
2223 return read(x);
2224 }
2225
readBE16Stream2226 inline uint16 readBE16() {
2227 uint16 x;
2228 return swap16(read(x));
2229 }
2230
readBE32Stream2231 inline uint32 readBE32() {
2232 uint32 x;
2233 return swap32(read(x));
2234 }
2235
read64Stream2236 inline uint64 read64() {
2237 uint64 x;
2238 return read(x);
2239 }
2240 };
2241
2242 Stream::Pack* Stream::packs[MAX_PACKS];
2243 Array<char*> Stream::fileList;
2244
2245 #ifdef OS_FILEIO_CACHE
osDataWrite(Stream * stream,const char * dir)2246 void osDataWrite(Stream *stream, const char *dir) {
2247 char path[255];
2248 strcpy(path, dir);
2249 strcat(path, stream->name);
2250 FILE *f = fopen(path, "wb");
2251 if (f) {
2252 fwrite(stream->data, 1, stream->size, f);
2253 fclose(f);
2254 if (stream->callback)
2255 stream->callback(new Stream(stream->name, stream->data, stream->size), stream->userData);
2256 } else
2257 if (stream->callback)
2258 stream->callback(NULL, stream->userData);
2259
2260 delete stream;
2261 }
2262
osDataRead(Stream * stream,const char * dir)2263 void osDataRead(Stream *stream, const char *dir) {
2264 char path[255];
2265 strcpy(path, dir);
2266 strcat(path, stream->name);
2267 FILE *f = fopen(path, "rb");
2268 if (f) {
2269 fseek(f, 0, SEEK_END);
2270 int size = (int)ftell(f);
2271 fseek(f, 0, SEEK_SET);
2272 char *data = new char[size];
2273 fread(data, 1, size, f);
2274 fclose(f);
2275 if (stream->callback)
2276 stream->callback(new Stream(stream->name, data, size), stream->userData);
2277 delete[] data;
2278 } else
2279 if (stream->callback)
2280 stream->callback(NULL, stream->userData);
2281 delete stream;
2282 }
2283
osCacheWrite(Stream * stream)2284 void osCacheWrite(Stream *stream) {
2285 osDataWrite(stream, cacheDir);
2286 }
2287
osCacheRead(Stream * stream)2288 void osCacheRead(Stream *stream) {
2289 osDataRead(stream, cacheDir);
2290 }
2291
osWriteSlot(Stream * stream)2292 void osWriteSlot(Stream *stream) {
2293 osDataWrite(stream, saveDir);
2294 }
2295
osReadSlot(Stream * stream)2296 void osReadSlot(Stream *stream) {
2297 osDataRead(stream, saveDir);
2298 }
2299
2300 #endif
2301
2302
2303 #ifdef OS_PTHREAD_MT
2304 #include <pthread.h>
2305
2306 // multi-threading
osMutexInit()2307 void* osMutexInit() {
2308 pthread_mutexattr_t attr;
2309 pthread_mutexattr_init(&attr);
2310 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
2311
2312 pthread_mutex_t *mutex = new pthread_mutex_t();
2313 pthread_mutex_init(mutex, &attr);
2314 return mutex;
2315 }
2316
osMutexFree(void * obj)2317 void osMutexFree(void *obj) {
2318 pthread_mutex_destroy((pthread_mutex_t*)obj);
2319 delete (pthread_mutex_t*)obj;
2320 }
2321
osMutexLock(void * obj)2322 void osMutexLock(void *obj) {
2323 pthread_mutex_lock((pthread_mutex_t*)obj);
2324 }
2325
osMutexUnlock(void * obj)2326 void osMutexUnlock(void *obj) {
2327 pthread_mutex_unlock((pthread_mutex_t*)obj);
2328 }
2329
osRWLockInit()2330 void* osRWLockInit() {
2331 pthread_rwlock_t *lock = new pthread_rwlock_t();
2332 pthread_rwlock_init(lock, NULL);
2333 return lock;
2334 }
2335
osRWLockFree(void * obj)2336 void osRWLockFree(void *obj) {
2337 pthread_rwlock_destroy((pthread_rwlock_t*)obj);
2338 delete (pthread_rwlock_t*)obj;
2339 }
2340
osRWLockRead(void * obj)2341 void osRWLockRead(void *obj) {
2342 pthread_rwlock_rdlock((pthread_rwlock_t*)obj);
2343 }
2344
osRWUnlockRead(void * obj)2345 void osRWUnlockRead(void *obj) {
2346 pthread_rwlock_unlock((pthread_rwlock_t*)obj);
2347 }
2348
osRWLockWrite(void * obj)2349 void osRWLockWrite(void *obj) {
2350 pthread_rwlock_wrlock((pthread_rwlock_t*)obj);
2351 }
2352
osRWUnlockWrite(void * obj)2353 void osRWUnlockWrite(void *obj) {
2354 pthread_rwlock_unlock((pthread_rwlock_t*)obj);
2355 }
2356 #endif
2357
2358
2359 static const uint32 BIT_MASK[] = {
2360 0x00000000,
2361 0x00000001, 0x00000003, 0x00000007, 0x0000000F,
2362 0x0000001F, 0x0000003F, 0x0000007F, 0x000000FF,
2363 0x000001FF, 0x000003FF, 0x000007FF, 0x00000FFF,
2364 0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF,
2365 0x0001FFFF, 0x0003FFFF, 0x0007FFFF, 0x000FFFFF,
2366 0x001FFFFF, 0x003FFFFF, 0x007FFFFF, 0x00FFFFFF,
2367 0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, 0x0FFFFFFF,
2368 0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF,
2369 };
2370
2371 // TODO: refactor for LE, BE, byte and word reading
2372 struct BitStream {
2373 uint8 *data;
2374 uint8 *end;
2375 uint16 index;
2376 uint16 value;
2377
BitStreamBitStream2378 BitStream(uint8 *data, int size) : data(data), end(data + size), index(0), value(0) {}
2379
readBitBitStream2380 inline uint32 readBit() {
2381 uint32 bit;
2382
2383 if (!index--) {
2384 value = *data++;
2385 index = 7;
2386 }
2387
2388 bit = value & 1;
2389 value >>= 1;
2390
2391 return bit;
2392 }
2393
readBitStream2394 uint32 read(int count) {
2395 uint32 bits = 0, mask = 1;
2396
2397 if (index == 0) {
2398 if (count > 7) {
2399 count -= 8;
2400 mask <<= 8;
2401 bits = *data++;
2402 }
2403 }
2404
2405 while (count--) {
2406 if (readBit())
2407 bits += mask;
2408 mask <<= 1;
2409 }
2410
2411 return bits;
2412 }
2413
readBEBitStream2414 uint8 readBE(int count) {
2415 uint32 bits = 0;
2416
2417 while (count--) {
2418 if (!index) {
2419 ASSERT(data < end);
2420 value = *data++;
2421 index = 8;
2422 }
2423
2424 bits <<= 1;
2425
2426 if (value & 0x80)
2427 bits |= 1;
2428
2429 value <<= 1;
2430 index--;
2431 }
2432
2433 return bits;
2434 }
2435
readBitBEBitStream2436 uint8 readBitBE() {
2437 return readBE(1);
2438 }
2439
readByteBitStream2440 uint8 readByte() {
2441 ASSERT(data < end);
2442 return *data++;
2443 }
2444
readWordBitStream2445 uint32 readWord(bool littleEndian) {
2446 uint8 a, b;
2447 if (littleEndian) {
2448 a = data[0];
2449 b = data[1];
2450 } else {
2451 b = data[0];
2452 a = data[1];
2453 }
2454 data += 2;
2455 return a + (b << 8);
2456 }
2457
readUBitStream2458 uint32 readU(int count) {
2459 if (!index) {
2460 value = readWord(true);
2461 index = 16;
2462 }
2463
2464 uint32 bits;
2465 if (count <= index) {
2466 bits = (value >> (index - count)) & BIT_MASK[count];
2467 index -= count;
2468 } else {
2469 bits = value & BIT_MASK[index];
2470 count -= index;
2471 index = 0;
2472
2473 while (count >= 16) {
2474 bits = (bits << 16) | readWord(true);
2475 count -= 16;
2476 }
2477
2478 if (count > 0) {
2479 value = readWord(true);
2480 index = 16 - count;
2481 bits = (bits << count) | (value >> index);
2482 }
2483 }
2484
2485 return bits;
2486 }
2487
skipBitStream2488 void skip(int count) {
2489 readU(count);
2490 }
2491 };
2492
2493
2494 template <int N>
2495 struct FixedStr {
2496 char data[N];
2497
getFixedStr2498 void get(char *dst) {
2499 memcpy(dst, data, sizeof(data));
2500 dst[sizeof(data)] = 0;
2501 }
2502
2503 FixedStr<N>& operator = (const char *str) {
2504 size_t len = min(sizeof(data), strlen(str));
2505 memset(data, 0, sizeof(data));
2506 memcpy(data, str, len);
2507 return *this;
2508 }
2509 };
2510
2511 typedef FixedStr<16> str16;
2512
2513 #endif
2514