rs_core.rsh revision f6a28c6a71d8929fb90ca83634a617d69531d87d
1275b1e98bb949643d35546f10f8b1af009349526Jason Sams#ifndef __RS_CORE_RSH__
2275b1e98bb949643d35546f10f8b1af009349526Jason Sams#define __RS_CORE_RSH__
3275b1e98bb949643d35546f10f8b1af009349526Jason Sams
4f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines#ifdef BCC_PREPARE_BC
5f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines#define _RS_STATIC  extern
6f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines#else
7f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines#define _RS_STATIC  static
8f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines#endif
9f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines
109bb32e1fd75e864071f18ef10976e8ba9fc0e252Shih-wei Liao// Debugging, print to the LOG a description string and a value.
119bb32e1fd75e864071f18ef10976e8ba9fc0e252Shih-wei Liaoextern void __attribute__((overloadable))
129bb32e1fd75e864071f18ef10976e8ba9fc0e252Shih-wei Liao    rsDebug(const char *, float);
139bb32e1fd75e864071f18ef10976e8ba9fc0e252Shih-wei Liaoextern void __attribute__((overloadable))
149bb32e1fd75e864071f18ef10976e8ba9fc0e252Shih-wei Liao    rsDebug(const char *, float, float);
159bb32e1fd75e864071f18ef10976e8ba9fc0e252Shih-wei Liaoextern void __attribute__((overloadable))
169bb32e1fd75e864071f18ef10976e8ba9fc0e252Shih-wei Liao    rsDebug(const char *, float, float, float);
179bb32e1fd75e864071f18ef10976e8ba9fc0e252Shih-wei Liaoextern void __attribute__((overloadable))
189bb32e1fd75e864071f18ef10976e8ba9fc0e252Shih-wei Liao    rsDebug(const char *, float, float, float, float);
199bb32e1fd75e864071f18ef10976e8ba9fc0e252Shih-wei Liaoextern void __attribute__((overloadable))
20df09719cbeb426a4c8279f2ce226b5874ad7c2c9Stephen Hines    rsDebug(const char *, double);
21df09719cbeb426a4c8279f2ce226b5874ad7c2c9Stephen Hinesextern void __attribute__((overloadable))
229bb32e1fd75e864071f18ef10976e8ba9fc0e252Shih-wei Liao    rsDebug(const char *, const rs_matrix4x4 *);
239bb32e1fd75e864071f18ef10976e8ba9fc0e252Shih-wei Liaoextern void __attribute__((overloadable))
249bb32e1fd75e864071f18ef10976e8ba9fc0e252Shih-wei Liao    rsDebug(const char *, const rs_matrix3x3 *);
259bb32e1fd75e864071f18ef10976e8ba9fc0e252Shih-wei Liaoextern void __attribute__((overloadable))
269bb32e1fd75e864071f18ef10976e8ba9fc0e252Shih-wei Liao    rsDebug(const char *, const rs_matrix2x2 *);
279bb32e1fd75e864071f18ef10976e8ba9fc0e252Shih-wei Liaoextern void __attribute__((overloadable))
289bb32e1fd75e864071f18ef10976e8ba9fc0e252Shih-wei Liao    rsDebug(const char *, int);
299bb32e1fd75e864071f18ef10976e8ba9fc0e252Shih-wei Liaoextern void __attribute__((overloadable))
309bb32e1fd75e864071f18ef10976e8ba9fc0e252Shih-wei Liao    rsDebug(const char *, uint);
319bb32e1fd75e864071f18ef10976e8ba9fc0e252Shih-wei Liaoextern void __attribute__((overloadable))
32df09719cbeb426a4c8279f2ce226b5874ad7c2c9Stephen Hines    rsDebug(const char *, long);
33df09719cbeb426a4c8279f2ce226b5874ad7c2c9Stephen Hinesextern void __attribute__((overloadable))
34df09719cbeb426a4c8279f2ce226b5874ad7c2c9Stephen Hines    rsDebug(const char *, unsigned long);
35df09719cbeb426a4c8279f2ce226b5874ad7c2c9Stephen Hinesextern void __attribute__((overloadable))
36df09719cbeb426a4c8279f2ce226b5874ad7c2c9Stephen Hines    rsDebug(const char *, long long);
37df09719cbeb426a4c8279f2ce226b5874ad7c2c9Stephen Hinesextern void __attribute__((overloadable))
38df09719cbeb426a4c8279f2ce226b5874ad7c2c9Stephen Hines    rsDebug(const char *, unsigned long long);
39df09719cbeb426a4c8279f2ce226b5874ad7c2c9Stephen Hinesextern void __attribute__((overloadable))
409bb32e1fd75e864071f18ef10976e8ba9fc0e252Shih-wei Liao    rsDebug(const char *, const void *);
419bb32e1fd75e864071f18ef10976e8ba9fc0e252Shih-wei Liao#define RS_DEBUG(a) rsDebug(#a, a)
429bb32e1fd75e864071f18ef10976e8ba9fc0e252Shih-wei Liao#define RS_DEBUG_MARKER rsDebug(__FILE__, __LINE__)
439bb32e1fd75e864071f18ef10976e8ba9fc0e252Shih-wei Liao
44f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC void __attribute__((overloadable)) rsDebug(const char *s, float2 v) {
457dce6bc09126187534ab0297c66b30149643b162Jason Sams    rsDebug(s, v.x, v.y);
467dce6bc09126187534ab0297c66b30149643b162Jason Sams}
47f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC void __attribute__((overloadable)) rsDebug(const char *s, float3 v) {
487dce6bc09126187534ab0297c66b30149643b162Jason Sams    rsDebug(s, v.x, v.y, v.z);
497dce6bc09126187534ab0297c66b30149643b162Jason Sams}
50f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC void __attribute__((overloadable)) rsDebug(const char *s, float4 v) {
517dce6bc09126187534ab0297c66b30149643b162Jason Sams    rsDebug(s, v.x, v.y, v.z, v.w);
527dce6bc09126187534ab0297c66b30149643b162Jason Sams}
53275b1e98bb949643d35546f10f8b1af009349526Jason Sams
54f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC uchar4 __attribute__((overloadable)) rsPackColorTo8888(float r, float g, float b)
55275b1e98bb949643d35546f10f8b1af009349526Jason Sams{
56275b1e98bb949643d35546f10f8b1af009349526Jason Sams    uchar4 c;
57275b1e98bb949643d35546f10f8b1af009349526Jason Sams    c.x = (uchar)(r * 255.f);
58275b1e98bb949643d35546f10f8b1af009349526Jason Sams    c.y = (uchar)(g * 255.f);
59275b1e98bb949643d35546f10f8b1af009349526Jason Sams    c.z = (uchar)(b * 255.f);
60275b1e98bb949643d35546f10f8b1af009349526Jason Sams    c.w = 255;
61275b1e98bb949643d35546f10f8b1af009349526Jason Sams    return c;
62275b1e98bb949643d35546f10f8b1af009349526Jason Sams}
63275b1e98bb949643d35546f10f8b1af009349526Jason Sams
64f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC uchar4 __attribute__((overloadable)) rsPackColorTo8888(float r, float g, float b, float a)
65275b1e98bb949643d35546f10f8b1af009349526Jason Sams{
66275b1e98bb949643d35546f10f8b1af009349526Jason Sams    uchar4 c;
67275b1e98bb949643d35546f10f8b1af009349526Jason Sams    c.x = (uchar)(r * 255.f);
68275b1e98bb949643d35546f10f8b1af009349526Jason Sams    c.y = (uchar)(g * 255.f);
69275b1e98bb949643d35546f10f8b1af009349526Jason Sams    c.z = (uchar)(b * 255.f);
70275b1e98bb949643d35546f10f8b1af009349526Jason Sams    c.w = (uchar)(a * 255.f);
71275b1e98bb949643d35546f10f8b1af009349526Jason Sams    return c;
72275b1e98bb949643d35546f10f8b1af009349526Jason Sams}
73275b1e98bb949643d35546f10f8b1af009349526Jason Sams
74f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC uchar4 __attribute__((overloadable)) rsPackColorTo8888(float3 color)
75275b1e98bb949643d35546f10f8b1af009349526Jason Sams{
76275b1e98bb949643d35546f10f8b1af009349526Jason Sams    color *= 255.f;
77275b1e98bb949643d35546f10f8b1af009349526Jason Sams    uchar4 c = {color.x, color.y, color.z, 255};
78275b1e98bb949643d35546f10f8b1af009349526Jason Sams    return c;
79275b1e98bb949643d35546f10f8b1af009349526Jason Sams}
80275b1e98bb949643d35546f10f8b1af009349526Jason Sams
81f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC uchar4 __attribute__((overloadable)) rsPackColorTo8888(float4 color)
82275b1e98bb949643d35546f10f8b1af009349526Jason Sams{
83275b1e98bb949643d35546f10f8b1af009349526Jason Sams    color *= 255.f;
84275b1e98bb949643d35546f10f8b1af009349526Jason Sams    uchar4 c = {color.x, color.y, color.z, color.w};
85275b1e98bb949643d35546f10f8b1af009349526Jason Sams    return c;
86275b1e98bb949643d35546f10f8b1af009349526Jason Sams}
87275b1e98bb949643d35546f10f8b1af009349526Jason Sams
88f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC float4 rsUnpackColor8888(uchar4 c)
89275b1e98bb949643d35546f10f8b1af009349526Jason Sams{
901b937f5c0d66a65daf07a45554c98a9f2481b9baJason Sams    float4 ret = (float4)0.0039156862745f;
911b937f5c0d66a65daf07a45554c98a9f2481b9baJason Sams    ret *= convert_float4(c);
92275b1e98bb949643d35546f10f8b1af009349526Jason Sams    return ret;
93275b1e98bb949643d35546f10f8b1af009349526Jason Sams}
94275b1e98bb949643d35546f10f8b1af009349526Jason Sams
952a63bf6c293d89c8e3725cfb7ee2add3dd3f0246Jason Sams//extern uchar4 __attribute__((overloadable)) rsPackColorTo565(float r, float g, float b);
962a63bf6c293d89c8e3725cfb7ee2add3dd3f0246Jason Sams//extern uchar4 __attribute__((overloadable)) rsPackColorTo565(float3);
972a63bf6c293d89c8e3725cfb7ee2add3dd3f0246Jason Sams//extern float4 rsUnpackColor565(uchar4);
982a63bf6c293d89c8e3725cfb7ee2add3dd3f0246Jason Sams
992a63bf6c293d89c8e3725cfb7ee2add3dd3f0246Jason Sams
1007fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams/////////////////////////////////////////////////////
1017fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams// Matrix ops
1027fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams/////////////////////////////////////////////////////
1037fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams
104f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC void __attribute__((overloadable))
1057fe6bce13c30b8d14dc833e06468666d28e56ee1Jason SamsrsMatrixSet(rs_matrix4x4 *m, uint32_t row, uint32_t col, float v) {
1067fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[row * 4 + col] = v;
1077fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams}
1087fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams
109f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC float __attribute__((overloadable))
1107fe6bce13c30b8d14dc833e06468666d28e56ee1Jason SamsrsMatrixGet(const rs_matrix4x4 *m, uint32_t row, uint32_t col) {
1117fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    return m->m[row * 4 + col];
1127fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams}
1137fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams
114f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC void __attribute__((overloadable))
1157fe6bce13c30b8d14dc833e06468666d28e56ee1Jason SamsrsMatrixSet(rs_matrix3x3 *m, uint32_t row, uint32_t col, float v) {
1167fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[row * 3 + col] = v;
1177fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams}
1187fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams
119f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC float __attribute__((overloadable))
1207fe6bce13c30b8d14dc833e06468666d28e56ee1Jason SamsrsMatrixGet(const rs_matrix3x3 *m, uint32_t row, uint32_t col) {
1217fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    return m->m[row * 3 + col];
1227fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams}
1237fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams
124f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC void __attribute__((overloadable))
1257fe6bce13c30b8d14dc833e06468666d28e56ee1Jason SamsrsMatrixSet(rs_matrix2x2 *m, uint32_t row, uint32_t col, float v) {
1267fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[row * 2 + col] = v;
1277fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams}
1287fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams
129f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC float __attribute__((overloadable))
1307fe6bce13c30b8d14dc833e06468666d28e56ee1Jason SamsrsMatrixGet(const rs_matrix2x2 *m, uint32_t row, uint32_t col) {
1317fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    return m->m[row * 2 + col];
1327fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams}
1337fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams
134f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC void __attribute__((overloadable))
1357fe6bce13c30b8d14dc833e06468666d28e56ee1Jason SamsrsMatrixLoadIdentity(rs_matrix4x4 *m) {
1367fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[0] = 1.f;
1377fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[1] = 0.f;
1387fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[2] = 0.f;
1397fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[3] = 0.f;
1407fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[4] = 0.f;
1417fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[5] = 1.f;
1427fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[6] = 0.f;
1437fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[7] = 0.f;
1447fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[8] = 0.f;
1457fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[9] = 0.f;
1467fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[10] = 1.f;
1477fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[11] = 0.f;
1487fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[12] = 0.f;
1497fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[13] = 0.f;
1507fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[14] = 0.f;
1517fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[15] = 1.f;
1527fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams}
1537fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams
154f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC void __attribute__((overloadable))
1557fe6bce13c30b8d14dc833e06468666d28e56ee1Jason SamsrsMatrixLoadIdentity(rs_matrix3x3 *m) {
1567fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[0] = 1.f;
1577fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[1] = 0.f;
1587fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[2] = 0.f;
1597fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[3] = 0.f;
1607fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[4] = 1.f;
1617fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[5] = 0.f;
1627fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[6] = 0.f;
1637fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[7] = 0.f;
1647fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[8] = 1.f;
1657fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams}
1667fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams
167f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC void __attribute__((overloadable))
1687fe6bce13c30b8d14dc833e06468666d28e56ee1Jason SamsrsMatrixLoadIdentity(rs_matrix2x2 *m) {
1697fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[0] = 1.f;
1707fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[1] = 0.f;
1717fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[2] = 0.f;
1727fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[3] = 1.f;
1737fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams}
1747fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams
175f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC void __attribute__((overloadable))
1767fe6bce13c30b8d14dc833e06468666d28e56ee1Jason SamsrsMatrixLoad(rs_matrix4x4 *m, const float *v) {
1777fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[0] = v[0];
1787fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[1] = v[1];
1797fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[2] = v[2];
1807fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[3] = v[3];
1817fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[4] = v[4];
1827fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[5] = v[5];
1837fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[6] = v[6];
1847fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[7] = v[7];
1857fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[8] = v[8];
1867fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[9] = v[9];
1877fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[10] = v[10];
1887fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[11] = v[11];
1897fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[12] = v[12];
1907fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[13] = v[13];
1917fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[14] = v[14];
1927fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[15] = v[15];
1937fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams}
1947fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams
195f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC void __attribute__((overloadable))
1967fe6bce13c30b8d14dc833e06468666d28e56ee1Jason SamsrsMatrixLoad(rs_matrix3x3 *m, const float *v) {
1977fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[0] = v[0];
1987fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[1] = v[1];
1997fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[2] = v[2];
2007fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[3] = v[3];
2017fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[4] = v[4];
2027fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[5] = v[5];
2037fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[6] = v[6];
2047fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[7] = v[7];
2057fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[8] = v[8];
2067fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams}
2077fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams
208f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC void __attribute__((overloadable))
2097fe6bce13c30b8d14dc833e06468666d28e56ee1Jason SamsrsMatrixLoad(rs_matrix2x2 *m, const float *v) {
2107fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[0] = v[0];
2117fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[1] = v[1];
2127fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[2] = v[2];
2137fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[3] = v[3];
2147fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams}
2157fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams
216f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC void __attribute__((overloadable))
2177fe6bce13c30b8d14dc833e06468666d28e56ee1Jason SamsrsMatrixLoad(rs_matrix4x4 *m, const rs_matrix4x4 *v) {
2187fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[0] = v->m[0];
2197fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[1] = v->m[1];
2207fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[2] = v->m[2];
2217fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[3] = v->m[3];
2227fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[4] = v->m[4];
2237fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[5] = v->m[5];
2247fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[6] = v->m[6];
2257fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[7] = v->m[7];
2267fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[8] = v->m[8];
2277fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[9] = v->m[9];
2287fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[10] = v->m[10];
2297fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[11] = v->m[11];
2307fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[12] = v->m[12];
2317fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[13] = v->m[13];
2327fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[14] = v->m[14];
2337fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[15] = v->m[15];
2347fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams}
2357fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams
236f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC void __attribute__((overloadable))
2377fe6bce13c30b8d14dc833e06468666d28e56ee1Jason SamsrsMatrixLoad(rs_matrix4x4 *m, const rs_matrix3x3 *v) {
2387fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[0] = v->m[0];
2397fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[1] = v->m[1];
2407fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[2] = v->m[2];
2417fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[3] = 0.f;
2427fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[4] = v->m[3];
2437fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[5] = v->m[4];
2447fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[6] = v->m[5];
2457fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[7] = 0.f;
2467fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[8] = v->m[6];
2477fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[9] = v->m[7];
2487fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[10] = v->m[8];
2497fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[11] = 0.f;
2507fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[12] = 0.f;
2517fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[13] = 0.f;
2527fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[14] = 0.f;
2537fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[15] = 1.f;
2547fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams}
2557fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams
256f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC void __attribute__((overloadable))
2577fe6bce13c30b8d14dc833e06468666d28e56ee1Jason SamsrsMatrixLoad(rs_matrix4x4 *m, const rs_matrix2x2 *v) {
2587fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[0] = v->m[0];
2597fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[1] = v->m[1];
2607fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[2] = 0.f;
2617fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[3] = 0.f;
2627fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[4] = v->m[3];
2637fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[5] = v->m[4];
2647fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[6] = 0.f;
2657fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[7] = 0.f;
2667fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[8] = v->m[6];
2677fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[9] = v->m[7];
2687fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[10] = 1.f;
2697fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[11] = 0.f;
2707fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[12] = 0.f;
2717fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[13] = 0.f;
2727fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[14] = 0.f;
2737fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[15] = 1.f;
2747fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams}
2757fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams
276f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC void __attribute__((overloadable))
2777fe6bce13c30b8d14dc833e06468666d28e56ee1Jason SamsrsMatrixLoad(rs_matrix3x3 *m, const rs_matrix3x3 *v) {
2787fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[0] = v->m[0];
2797fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[1] = v->m[1];
2807fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[2] = v->m[2];
2817fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[3] = v->m[3];
2827fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[4] = v->m[4];
2837fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[5] = v->m[5];
2847fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[6] = v->m[6];
2857fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[7] = v->m[7];
2867fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[8] = v->m[8];
2877fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams}
2887fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams
289f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC void __attribute__((overloadable))
2907fe6bce13c30b8d14dc833e06468666d28e56ee1Jason SamsrsMatrixLoad(rs_matrix2x2 *m, const rs_matrix2x2 *v) {
2917fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[0] = v->m[0];
2927fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[1] = v->m[1];
2937fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[2] = v->m[2];
2947fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[3] = v->m[3];
2957fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams}
2967fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams
297f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC void __attribute__((overloadable))
2987fe6bce13c30b8d14dc833e06468666d28e56ee1Jason SamsrsMatrixLoadRotate(rs_matrix4x4 *m, float rot, float x, float y, float z) {
2997fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    float c, s;
3007fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[3] = 0;
3017fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[7] = 0;
3027fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[11]= 0;
3037fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[12]= 0;
3047fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[13]= 0;
3057fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[14]= 0;
3067fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[15]= 1;
3077fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    rot *= (float)(M_PI / 180.0f);
3087fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    c = cos(rot);
3097fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    s = sin(rot);
3107fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams
3117fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    const float len = x*x + y*y + z*z;
31229a3fd50d1c85ef32b68838072452674ae311594Jason Sams    if (len != 1) {
3137fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams        const float recipLen = 1.f / sqrt(len);
3147fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams        x *= recipLen;
3157fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams        y *= recipLen;
3167fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams        z *= recipLen;
3177fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    }
3187fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    const float nc = 1.0f - c;
3197fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    const float xy = x * y;
3207fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    const float yz = y * z;
3217fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    const float zx = z * x;
3227fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    const float xs = x * s;
3237fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    const float ys = y * s;
3247fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    const float zs = z * s;
3257fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[ 0] = x*x*nc +  c;
3267fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[ 4] =  xy*nc - zs;
3277fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[ 8] =  zx*nc + ys;
3287fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[ 1] =  xy*nc + zs;
3297fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[ 5] = y*y*nc +  c;
3307fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[ 9] =  yz*nc - xs;
3317fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[ 2] =  zx*nc - ys;
3327fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[ 6] =  yz*nc + xs;
3337fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[10] = z*z*nc +  c;
3347fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams}
3357fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams
336f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC void __attribute__((overloadable))
3377fe6bce13c30b8d14dc833e06468666d28e56ee1Jason SamsrsMatrixLoadScale(rs_matrix4x4 *m, float x, float y, float z) {
3387fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    rsMatrixLoadIdentity(m);
3397fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[0] = x;
3407fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[5] = y;
3417fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[10] = z;
3427fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams}
3437fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams
344f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC void __attribute__((overloadable))
3457fe6bce13c30b8d14dc833e06468666d28e56ee1Jason SamsrsMatrixLoadTranslate(rs_matrix4x4 *m, float x, float y, float z) {
3467fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    rsMatrixLoadIdentity(m);
3477fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[12] = x;
3487fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[13] = y;
3497fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[14] = z;
3507fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams}
3517fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams
352f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC void __attribute__((overloadable))
3537fe6bce13c30b8d14dc833e06468666d28e56ee1Jason SamsrsMatrixLoadMultiply(rs_matrix4x4 *m, const rs_matrix4x4 *lhs, const rs_matrix4x4 *rhs) {
3547fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    for (int i=0 ; i<4 ; i++) {
3557fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams        float ri0 = 0;
3567fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams        float ri1 = 0;
3577fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams        float ri2 = 0;
3587fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams        float ri3 = 0;
3597fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams        for (int j=0 ; j<4 ; j++) {
3607fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams            const float rhs_ij = rsMatrixGet(rhs, i,j);
3617fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams            ri0 += rsMatrixGet(lhs, j, 0) * rhs_ij;
3627fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams            ri1 += rsMatrixGet(lhs, j, 1) * rhs_ij;
3637fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams            ri2 += rsMatrixGet(lhs, j, 2) * rhs_ij;
3647fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams            ri3 += rsMatrixGet(lhs, j, 3) * rhs_ij;
3657fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams        }
3667fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams        rsMatrixSet(m, i, 0, ri0);
3677fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams        rsMatrixSet(m, i, 1, ri1);
3687fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams        rsMatrixSet(m, i, 2, ri2);
3697fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams        rsMatrixSet(m, i, 3, ri3);
3707fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    }
3717fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams}
3727fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams
373f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC void __attribute__((overloadable))
3747fe6bce13c30b8d14dc833e06468666d28e56ee1Jason SamsrsMatrixMultiply(rs_matrix4x4 *m, const rs_matrix4x4 *rhs) {
3757fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    rs_matrix4x4 mt;
3767fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    rsMatrixLoadMultiply(&mt, m, rhs);
3777fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    rsMatrixLoad(m, &mt);
3787fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams}
3797fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams
380f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC void __attribute__((overloadable))
3817fe6bce13c30b8d14dc833e06468666d28e56ee1Jason SamsrsMatrixLoadMultiply(rs_matrix3x3 *m, const rs_matrix3x3 *lhs, const rs_matrix3x3 *rhs) {
3827fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    for (int i=0 ; i<3 ; i++) {
3837fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams        float ri0 = 0;
3847fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams        float ri1 = 0;
3857fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams        float ri2 = 0;
3867fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams        for (int j=0 ; j<3 ; j++) {
3877fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams            const float rhs_ij = rsMatrixGet(rhs, i,j);
3887fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams            ri0 += rsMatrixGet(lhs, j, 0) * rhs_ij;
3897fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams            ri1 += rsMatrixGet(lhs, j, 1) * rhs_ij;
3907fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams            ri2 += rsMatrixGet(lhs, j, 2) * rhs_ij;
3917fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams        }
3927fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams        rsMatrixSet(m, i, 0, ri0);
3937fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams        rsMatrixSet(m, i, 1, ri1);
3947fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams        rsMatrixSet(m, i, 2, ri2);
3957fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    }
3967fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams}
3977fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams
398f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC void __attribute__((overloadable))
3997fe6bce13c30b8d14dc833e06468666d28e56ee1Jason SamsrsMatrixMultiply(rs_matrix3x3 *m, const rs_matrix3x3 *rhs) {
4007fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    rs_matrix3x3 mt;
4017fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    rsMatrixLoadMultiply(&mt, m, rhs);
4027fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    rsMatrixLoad(m, &mt);
4037fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams}
4047fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams
405f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC void __attribute__((overloadable))
4067fe6bce13c30b8d14dc833e06468666d28e56ee1Jason SamsrsMatrixLoadMultiply(rs_matrix2x2 *m, const rs_matrix2x2 *lhs, const rs_matrix2x2 *rhs) {
4077fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    for (int i=0 ; i<2 ; i++) {
4087fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams        float ri0 = 0;
4097fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams        float ri1 = 0;
4107fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams        for (int j=0 ; j<2 ; j++) {
4117fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams            const float rhs_ij = rsMatrixGet(rhs, i,j);
4127fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams            ri0 += rsMatrixGet(lhs, j, 0) * rhs_ij;
4137fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams            ri1 += rsMatrixGet(lhs, j, 1) * rhs_ij;
4147fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams        }
4157fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams        rsMatrixSet(m, i, 0, ri0);
4167fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams        rsMatrixSet(m, i, 1, ri1);
4177fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    }
4187fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams}
4197fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams
420f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC void __attribute__((overloadable))
4217fe6bce13c30b8d14dc833e06468666d28e56ee1Jason SamsrsMatrixMultiply(rs_matrix2x2 *m, const rs_matrix2x2 *rhs) {
4227fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    rs_matrix2x2 mt;
4237fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    rsMatrixLoadMultiply(&mt, m, rhs);
4247fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    rsMatrixLoad(m, &mt);
4257fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams}
4267fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams
427f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC void __attribute__((overloadable))
4287fe6bce13c30b8d14dc833e06468666d28e56ee1Jason SamsrsMatrixRotate(rs_matrix4x4 *m, float rot, float x, float y, float z) {
4297fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    rs_matrix4x4 m1;
4307fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    rsMatrixLoadRotate(&m1, rot, x, y, z);
4317fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    rsMatrixMultiply(m, &m1);
4327fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams}
4337fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams
434f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC void __attribute__((overloadable))
4357fe6bce13c30b8d14dc833e06468666d28e56ee1Jason SamsrsMatrixScale(rs_matrix4x4 *m, float x, float y, float z) {
4367fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    rs_matrix4x4 m1;
4377fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    rsMatrixLoadScale(&m1, x, y, z);
4387fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    rsMatrixMultiply(m, &m1);
4397fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams}
4407fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams
441f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC void __attribute__((overloadable))
4427fe6bce13c30b8d14dc833e06468666d28e56ee1Jason SamsrsMatrixTranslate(rs_matrix4x4 *m, float x, float y, float z) {
4437fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    rs_matrix4x4 m1;
4447fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    rsMatrixLoadTranslate(&m1, x, y, z);
4457fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    rsMatrixMultiply(m, &m1);
4467fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams}
4477fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams
448f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC void __attribute__((overloadable))
4497fe6bce13c30b8d14dc833e06468666d28e56ee1Jason SamsrsMatrixLoadOrtho(rs_matrix4x4 *m, float left, float right, float bottom, float top, float near, float far) {
4507fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    rsMatrixLoadIdentity(m);
4517fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[0] = 2.f / (right - left);
4527fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[5] = 2.f / (top - bottom);
4537fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[10]= -2.f / (far - near);
4547fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[12]= -(right + left) / (right - left);
4557fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[13]= -(top + bottom) / (top - bottom);
4567fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[14]= -(far + near) / (far - near);
4577fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams}
4587fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams
459f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC void __attribute__((overloadable))
4607fe6bce13c30b8d14dc833e06468666d28e56ee1Jason SamsrsMatrixLoadFrustum(rs_matrix4x4 *m, float left, float right, float bottom, float top, float near, float far) {
4617fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    rsMatrixLoadIdentity(m);
4627fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[0] = 2.f * near / (right - left);
4637fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[5] = 2.f * near / (top - bottom);
4647fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[8] = (right + left) / (right - left);
4657fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[9] = (top + bottom) / (top - bottom);
4667fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[10]= -(far + near) / (far - near);
4677fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[11]= -1.f;
4687fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[14]= -2.f * far * near / (far - near);
4697fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    m->m[15]= 0.f;
4707fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams}
4717fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams
472f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC void __attribute__((overloadable))
473c8dc45cc95cd144038c153f3a4657527d5a7c0b6Alex SakhartchoukrsMatrixLoadPerspective(rs_matrix4x4* m, float fovy, float aspect, float near, float far) {
474c8dc45cc95cd144038c153f3a4657527d5a7c0b6Alex Sakhartchouk    float top = near * tan((float) (fovy * M_PI / 360.0f));
475c8dc45cc95cd144038c153f3a4657527d5a7c0b6Alex Sakhartchouk    float bottom = -top;
476c8dc45cc95cd144038c153f3a4657527d5a7c0b6Alex Sakhartchouk    float left = bottom * aspect;
477c8dc45cc95cd144038c153f3a4657527d5a7c0b6Alex Sakhartchouk    float right = top * aspect;
478c8dc45cc95cd144038c153f3a4657527d5a7c0b6Alex Sakhartchouk    rsMatrixLoadFrustum(m, left, right, bottom, top, near, far);
479c8dc45cc95cd144038c153f3a4657527d5a7c0b6Alex Sakhartchouk}
480c8dc45cc95cd144038c153f3a4657527d5a7c0b6Alex Sakhartchouk
481f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC float4 __attribute__((overloadable))
4827fe6bce13c30b8d14dc833e06468666d28e56ee1Jason SamsrsMatrixMultiply(rs_matrix4x4 *m, float4 in) {
4837fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    float4 ret;
4847fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    ret.x = (m->m[0] * in.x) + (m->m[4] * in.y) + (m->m[8] * in.z) + (m->m[12] * in.w);
4857fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    ret.y = (m->m[1] * in.x) + (m->m[5] * in.y) + (m->m[9] * in.z) + (m->m[13] * in.w);
4867fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    ret.z = (m->m[2] * in.x) + (m->m[6] * in.y) + (m->m[10] * in.z) + (m->m[14] * in.w);
4877fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    ret.w = (m->m[3] * in.x) + (m->m[7] * in.y) + (m->m[11] * in.z) + (m->m[15] * in.w);
4887fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    return ret;
4897fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams}
4907fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams
491f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC float4 __attribute__((overloadable))
4927fe6bce13c30b8d14dc833e06468666d28e56ee1Jason SamsrsMatrixMultiply(rs_matrix4x4 *m, float3 in) {
4937fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    float4 ret;
4947fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    ret.x = (m->m[0] * in.x) + (m->m[4] * in.y) + (m->m[8] * in.z) + m->m[12];
4957fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    ret.y = (m->m[1] * in.x) + (m->m[5] * in.y) + (m->m[9] * in.z) + m->m[13];
4967fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    ret.z = (m->m[2] * in.x) + (m->m[6] * in.y) + (m->m[10] * in.z) + m->m[14];
4977fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    ret.w = (m->m[3] * in.x) + (m->m[7] * in.y) + (m->m[11] * in.z) + m->m[15];
4987fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    return ret;
4997fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams}
5007fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams
501f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC float4 __attribute__((overloadable))
5027fe6bce13c30b8d14dc833e06468666d28e56ee1Jason SamsrsMatrixMultiply(rs_matrix4x4 *m, float2 in) {
5037fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    float4 ret;
5047fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    ret.x = (m->m[0] * in.x) + (m->m[4] * in.y) + m->m[12];
5057fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    ret.y = (m->m[1] * in.x) + (m->m[5] * in.y) + m->m[13];
5067fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    ret.z = (m->m[2] * in.x) + (m->m[6] * in.y) + m->m[14];
5077fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    ret.w = (m->m[3] * in.x) + (m->m[7] * in.y) + m->m[15];
5087fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    return ret;
5097fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams}
5107fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams
511f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC float3 __attribute__((overloadable))
5127fe6bce13c30b8d14dc833e06468666d28e56ee1Jason SamsrsMatrixMultiply(rs_matrix3x3 *m, float3 in) {
5137fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    float3 ret;
5147fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    ret.x = (m->m[0] * in.x) + (m->m[3] * in.y) + (m->m[6] * in.z);
5157fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    ret.y = (m->m[1] * in.x) + (m->m[4] * in.y) + (m->m[7] * in.z);
5167fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    ret.z = (m->m[2] * in.x) + (m->m[5] * in.y) + (m->m[8] * in.z);
5177fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    return ret;
5187fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams}
5197fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams
520f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC float3 __attribute__((overloadable))
5217fe6bce13c30b8d14dc833e06468666d28e56ee1Jason SamsrsMatrixMultiply(rs_matrix3x3 *m, float2 in) {
5227fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    float3 ret;
5237fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    ret.x = (m->m[0] * in.x) + (m->m[3] * in.y);
5247fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    ret.y = (m->m[1] * in.x) + (m->m[4] * in.y);
5257fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    ret.z = (m->m[2] * in.x) + (m->m[5] * in.y);
5267fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    return ret;
5277fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams}
5287fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams
529f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC float2 __attribute__((overloadable))
5307fe6bce13c30b8d14dc833e06468666d28e56ee1Jason SamsrsMatrixMultiply(rs_matrix2x2 *m, float2 in) {
5317fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    float2 ret;
5327fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    ret.x = (m->m[0] * in.x) + (m->m[2] * in.y);
5337fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    ret.y = (m->m[1] * in.x) + (m->m[3] * in.y);
5347fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    return ret;
5357fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams}
5367fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams
53720c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk// Returns true if the matrix was successfully inversed
538f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC bool __attribute__((overloadable))
53920c6c1febce7cdf398c58287bf506b3a4a210285Alex SakhartchoukrsMatrixInverse(rs_matrix4x4 *m) {
54020c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk    rs_matrix4x4 result;
54120c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk
54220c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk    int i, j;
54320c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk    for (i = 0; i < 4; ++i) {
54420c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk        for (j = 0; j < 4; ++j) {
54520c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk            // computeCofactor for int i, int j
54620c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk            int c0 = (i+1) % 4;
54720c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk            int c1 = (i+2) % 4;
54820c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk            int c2 = (i+3) % 4;
54920c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk            int r0 = (j+1) % 4;
55020c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk            int r1 = (j+2) % 4;
55120c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk            int r2 = (j+3) % 4;
55220c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk
55320c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk            float minor = (m->m[c0 + 4*r0] * (m->m[c1 + 4*r1] * m->m[c2 + 4*r2] - m->m[c1 + 4*r2] * m->m[c2 + 4*r1]))
55420c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk                         - (m->m[c0 + 4*r1] * (m->m[c1 + 4*r0] * m->m[c2 + 4*r2] - m->m[c1 + 4*r2] * m->m[c2 + 4*r0]))
55520c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk                         + (m->m[c0 + 4*r2] * (m->m[c1 + 4*r0] * m->m[c2 + 4*r1] - m->m[c1 + 4*r1] * m->m[c2 + 4*r0]));
55620c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk
55720c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk            float cofactor = (i+j) & 1 ? -minor : minor;
55820c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk
55920c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk            result.m[4*i + j] = cofactor;
56020c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk        }
56120c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk    }
56220c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk
56320c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk    // Dot product of 0th column of source and 0th row of result
56420c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk    float det = m->m[0]*result.m[0] + m->m[4]*result.m[1] +
56520c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk                 m->m[8]*result.m[2] + m->m[12]*result.m[3];
56620c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk
56720c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk    if (fabs(det) < 1e-6) {
56820c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk        return false;
56920c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk    }
57020c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk
57120c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk    det = 1.0f / det;
57220c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk    for (i = 0; i < 16; ++i) {
57320c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk        m->m[i] = result.m[i] * det;
57420c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk    }
57520c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk
57620c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk    return true;
57720c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk}
57820c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk
57920c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk// Returns true if the matrix was successfully inversed
580f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC bool __attribute__((overloadable))
58120c6c1febce7cdf398c58287bf506b3a4a210285Alex SakhartchoukrsMatrixInverseTranspose(rs_matrix4x4 *m) {
58220c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk    rs_matrix4x4 result;
58320c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk
58420c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk    int i, j;
58520c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk    for (i = 0; i < 4; ++i) {
58620c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk        for (j = 0; j < 4; ++j) {
58720c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk            // computeCofactor for int i, int j
58820c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk            int c0 = (i+1) % 4;
58920c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk            int c1 = (i+2) % 4;
59020c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk            int c2 = (i+3) % 4;
59120c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk            int r0 = (j+1) % 4;
59220c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk            int r1 = (j+2) % 4;
59320c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk            int r2 = (j+3) % 4;
59420c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk
59520c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk            float minor = (m->m[c0 + 4*r0] * (m->m[c1 + 4*r1] * m->m[c2 + 4*r2] - m->m[c1 + 4*r2] * m->m[c2 + 4*r1]))
59620c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk                         - (m->m[c0 + 4*r1] * (m->m[c1 + 4*r0] * m->m[c2 + 4*r2] - m->m[c1 + 4*r2] * m->m[c2 + 4*r0]))
59720c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk                         + (m->m[c0 + 4*r2] * (m->m[c1 + 4*r0] * m->m[c2 + 4*r1] - m->m[c1 + 4*r1] * m->m[c2 + 4*r0]));
59820c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk
59920c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk            float cofactor = (i+j) & 1 ? -minor : minor;
60020c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk
60120c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk            result.m[4*j + i] = cofactor;
60220c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk        }
60320c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk    }
60420c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk
60520c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk    // Dot product of 0th column of source and 0th column of result
60620c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk    float det = m->m[0]*result.m[0] + m->m[4]*result.m[4] +
60720c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk                 m->m[8]*result.m[8] + m->m[12]*result.m[12];
60820c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk
60920c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk    if (fabs(det) < 1e-6) {
61020c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk        return false;
61120c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk    }
61220c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk
61320c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk    det = 1.0f / det;
61420c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk    for (i = 0; i < 16; ++i) {
61520c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk        m->m[i] = result.m[i] * det;
61620c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk    }
61720c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk
61820c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk    return true;
61920c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk}
62020c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk
621f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC void __attribute__((overloadable))
62220c6c1febce7cdf398c58287bf506b3a4a210285Alex SakhartchoukrsMatrixTranspose(rs_matrix4x4 *m) {
62320c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk    int i, j;
62420c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk    float temp;
62520c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk    for (i = 0; i < 3; ++i) {
62620c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk        for (j = i + 1; j < 4; ++j) {
62720c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk            temp = m->m[i*4 + j];
62820c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk            m->m[i*4 + j] = m->m[j*4 + i];
62920c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk            m->m[j*4 + i] = temp;
63020c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk        }
63120c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk    }
63220c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk}
63320c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk
634f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC void __attribute__((overloadable))
63520c6c1febce7cdf398c58287bf506b3a4a210285Alex SakhartchoukrsMatrixTranspose(rs_matrix3x3 *m) {
63620c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk    int i, j;
63720c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk    float temp;
63820c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk    for (i = 0; i < 2; ++i) {
63920c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk        for (j = i + 1; j < 3; ++j) {
64020c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk            temp = m->m[i*3 + j];
64120c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk            m->m[i*3 + j] = m->m[j*4 + i];
64220c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk            m->m[j*3 + i] = temp;
64320c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk        }
64420c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk    }
64520c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk}
64620c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk
647f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC void __attribute__((overloadable))
64820c6c1febce7cdf398c58287bf506b3a4a210285Alex SakhartchoukrsMatrixTranspose(rs_matrix2x2 *m) {
64920c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk    float temp = m->m[1];
65020c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk    m->m[1] = m->m[2];
65120c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk    m->m[2] = temp;
65220c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk}
65320c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk
65429858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk/////////////////////////////////////////////////////
65529858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk// quaternion ops
65629858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk/////////////////////////////////////////////////////
65729858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk
658f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC void __attribute__((overloadable))
65929858059ffff967607f7583ae9146dc4c720f92eAlex SakhartchoukrsQuaternionSet(rs_quaternion *q, float w, float x, float y, float z) {
66029858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    q->w = w;
66129858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    q->x = x;
66229858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    q->y = y;
66329858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    q->z = z;
66429858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk}
66529858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk
666f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC void __attribute__((overloadable))
66729858059ffff967607f7583ae9146dc4c720f92eAlex SakhartchoukrsQuaternionSet(rs_quaternion *q, const rs_quaternion *rhs) {
66829858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    q->w = rhs->w;
66929858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    q->x = rhs->x;
67029858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    q->y = rhs->y;
67129858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    q->z = rhs->z;
67229858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk}
67329858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk
674f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC void __attribute__((overloadable))
67529858059ffff967607f7583ae9146dc4c720f92eAlex SakhartchoukrsQuaternionMultiply(rs_quaternion *q, float s) {
67629858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    q->w *= s;
67729858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    q->x *= s;
67829858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    q->y *= s;
67929858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    q->z *= s;
68029858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk}
68129858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk
682f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC void __attribute__((overloadable))
68329858059ffff967607f7583ae9146dc4c720f92eAlex SakhartchoukrsQuaternionMultiply(rs_quaternion *q, const rs_quaternion *rhs) {
68429858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    q->w = -q->x*rhs->x - q->y*rhs->y - q->z*rhs->z + q->w*rhs->w;
68529858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    q->x =  q->x*rhs->w + q->y*rhs->z - q->z*rhs->y + q->w*rhs->x;
68629858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    q->y = -q->x*rhs->z + q->y*rhs->w + q->z*rhs->z + q->w*rhs->y;
68729858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    q->z =  q->x*rhs->y - q->y*rhs->x + q->z*rhs->w + q->w*rhs->z;
68829858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk}
68929858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk
690f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC void
69129858059ffff967607f7583ae9146dc4c720f92eAlex SakhartchoukrsQuaternionAdd(rs_quaternion *q, const rs_quaternion *rhs) {
69229858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    q->w *= rhs->w;
69329858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    q->x *= rhs->x;
69429858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    q->y *= rhs->y;
69529858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    q->z *= rhs->z;
69629858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk}
69729858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk
698f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC void
69929858059ffff967607f7583ae9146dc4c720f92eAlex SakhartchoukrsQuaternionLoadRotateUnit(rs_quaternion *q, float rot, float x, float y, float z) {
70029858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    rot *= (float)(M_PI / 180.0f) * 0.5f;
70129858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    float c = cos(rot);
70229858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    float s = sin(rot);
70329858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk
70429858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    q->w = c;
70529858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    q->x = x * s;
70629858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    q->y = y * s;
70729858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    q->z = z * s;
70829858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk}
70929858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk
710f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC void
71129858059ffff967607f7583ae9146dc4c720f92eAlex SakhartchoukrsQuaternionLoadRotate(rs_quaternion *q, float rot, float x, float y, float z) {
71229858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    const float len = x*x + y*y + z*z;
71329858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    if (len != 1) {
71429858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk        const float recipLen = 1.f / sqrt(len);
71529858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk        x *= recipLen;
71629858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk        y *= recipLen;
71729858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk        z *= recipLen;
71829858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    }
71929858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    rsQuaternionLoadRotateUnit(q, rot, x, y, z);
72029858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk}
72129858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk
722f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC void
72329858059ffff967607f7583ae9146dc4c720f92eAlex SakhartchoukrsQuaternionConjugate(rs_quaternion *q) {
72429858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    q->x = -q->x;
72529858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    q->y = -q->y;
72629858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    q->z = -q->z;
72729858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk}
72829858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk
729f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC float
73029858059ffff967607f7583ae9146dc4c720f92eAlex SakhartchoukrsQuaternionDot(const rs_quaternion *q0, const rs_quaternion *q1) {
73129858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    return q0->w*q1->w + q0->x*q1->x + q0->y*q1->y + q0->z*q1->z;
73229858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk}
73329858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk
734f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC void
73529858059ffff967607f7583ae9146dc4c720f92eAlex SakhartchoukrsQuaternionNormalize(rs_quaternion *q) {
73629858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    const float len = rsQuaternionDot(q, q);
73729858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    if (len != 1) {
73829858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk        const float recipLen = 1.f / sqrt(len);
73929858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk        rsQuaternionMultiply(q, recipLen);
74029858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    }
74129858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk}
74229858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk
743f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC void
74429858059ffff967607f7583ae9146dc4c720f92eAlex SakhartchoukrsQuaternionSlerp(rs_quaternion *q, const rs_quaternion *q0, const rs_quaternion *q1, float t) {
745afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    if (t <= 0.0f) {
74629858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk        rsQuaternionSet(q, q0);
74729858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk        return;
74829858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    }
749afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    if (t >= 1.0f) {
75029858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk        rsQuaternionSet(q, q1);
75129858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk        return;
75229858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    }
75329858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk
75429858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    rs_quaternion tempq0, tempq1;
75529858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    rsQuaternionSet(&tempq0, q0);
75629858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    rsQuaternionSet(&tempq1, q1);
75729858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk
75829858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    float angle = rsQuaternionDot(q0, q1);
759afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    if (angle < 0) {
76029858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk        rsQuaternionMultiply(&tempq0, -1.0f);
76129858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk        angle *= -1.0f;
76229858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    }
76329858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk
76429858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    float scale, invScale;
76529858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    if (angle + 1.0f > 0.05f) {
76629858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk        if (1.0f - angle >= 0.05f) {
76729858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk            float theta = acos(angle);
76829858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk            float invSinTheta = 1.0f / sin(theta);
76929858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk            scale = sin(theta * (1.0f - t)) * invSinTheta;
77029858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk            invScale = sin(theta * t) * invSinTheta;
771afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk        } else {
77229858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk            scale = 1.0f - t;
77329858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk            invScale = t;
77429858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk        }
775afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    } else {
77629858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk        rsQuaternionSet(&tempq1, tempq0.z, -tempq0.y, tempq0.x, -tempq0.w);
77729858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk        scale = sin(M_PI * (0.5f - t));
77829858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk        invScale = sin(M_PI * t);
77929858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    }
78029858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk
78129858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    rsQuaternionSet(q, tempq0.w*scale + tempq1.w*invScale, tempq0.x*scale + tempq1.x*invScale,
78229858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk                        tempq0.y*scale + tempq1.y*invScale, tempq0.z*scale + tempq1.z*invScale);
78329858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk}
78429858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk
785f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines_RS_STATIC void rsQuaternionGetMatrixUnit(rs_matrix4x4 *m, const rs_quaternion *q) {
78629858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    float x2 = 2.0f * q->x * q->x;
78729858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    float y2 = 2.0f * q->y * q->y;
78829858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    float z2 = 2.0f * q->z * q->z;
78929858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    float xy = 2.0f * q->x * q->y;
79029858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    float wz = 2.0f * q->w * q->z;
79129858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    float xz = 2.0f * q->x * q->z;
79229858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    float wy = 2.0f * q->w * q->y;
79329858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    float wx = 2.0f * q->w * q->x;
79429858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    float yz = 2.0f * q->y * q->z;
79529858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk
79629858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    m->m[0] = 1.0f - y2 - z2;
79729858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    m->m[1] = xy - wz;
79829858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    m->m[2] = xz + wy;
79929858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    m->m[3] = 0.0f;
80029858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk
80129858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    m->m[4] = xy + wz;
80229858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    m->m[5] = 1.0f - x2 - z2;
80329858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    m->m[6] = yz - wx;
80429858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    m->m[7] = 0.0f;
80529858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk
80629858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    m->m[8] = xz - wy;
80729858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    m->m[9] = yz - wx;
80829858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    m->m[10] = 1.0f - x2 - y2;
80929858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    m->m[11] = 0.0f;
81029858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk
81129858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    m->m[12] = 0.0f;
81229858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    m->m[13] = 0.0f;
81329858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    m->m[14] = 0.0f;
81429858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk    m->m[15] = 1.0f;
81529858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk}
81629858059ffff967607f7583ae9146dc4c720f92eAlex Sakhartchouk
81795333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk/////////////////////////////////////////////////////
81895333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk// utility funcs
81995333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk/////////////////////////////////////////////////////
820f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines__inline__ _RS_STATIC void __attribute__((overloadable, always_inline))
82195333f998fd4a983f89e5128e85f6f710d200bd9Alex SakhartchoukrsExtractFrustumPlanes(const rs_matrix4x4 *modelViewProj,
82295333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk                         float4 *left, float4 *right,
82395333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk                         float4 *top, float4 *bottom,
82495333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk                         float4 *near, float4 *far) {
82595333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    // x y z w = a b c d in the plane equation
82695333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    left->x = modelViewProj->m[3] + modelViewProj->m[0];
82795333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    left->y = modelViewProj->m[7] + modelViewProj->m[4];
82895333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    left->z = modelViewProj->m[11] + modelViewProj->m[8];
82995333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    left->w = modelViewProj->m[15] + modelViewProj->m[12];
83095333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk
83195333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    right->x = modelViewProj->m[3] - modelViewProj->m[0];
83295333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    right->y = modelViewProj->m[7] - modelViewProj->m[4];
83395333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    right->z = modelViewProj->m[11] - modelViewProj->m[8];
83495333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    right->w = modelViewProj->m[15] - modelViewProj->m[12];
83595333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk
83695333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    top->x = modelViewProj->m[3] - modelViewProj->m[1];
83795333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    top->y = modelViewProj->m[7] - modelViewProj->m[5];
83895333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    top->z = modelViewProj->m[11] - modelViewProj->m[9];
83995333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    top->w = modelViewProj->m[15] - modelViewProj->m[13];
84095333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk
84195333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    bottom->x = modelViewProj->m[3] + modelViewProj->m[1];
84295333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    bottom->y = modelViewProj->m[7] + modelViewProj->m[5];
84395333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    bottom->z = modelViewProj->m[11] + modelViewProj->m[9];
84495333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    bottom->w = modelViewProj->m[15] + modelViewProj->m[13];
84595333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk
84695333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    near->x = modelViewProj->m[3] + modelViewProj->m[2];
84795333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    near->y = modelViewProj->m[7] + modelViewProj->m[6];
84895333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    near->z = modelViewProj->m[11] + modelViewProj->m[10];
84995333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    near->w = modelViewProj->m[15] + modelViewProj->m[14];
85095333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk
85195333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    far->x = modelViewProj->m[3] - modelViewProj->m[2];
85295333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    far->y = modelViewProj->m[7] - modelViewProj->m[6];
85395333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    far->z = modelViewProj->m[11] - modelViewProj->m[10];
85495333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    far->w = modelViewProj->m[15] - modelViewProj->m[14];
85595333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk
85695333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    float len = length(left->xyz);
85795333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    *left /= len;
85895333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    len = length(right->xyz);
85995333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    *right /= len;
86095333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    len = length(top->xyz);
86195333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    *top /= len;
86295333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    len = length(bottom->xyz);
86395333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    *bottom /= len;
86495333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    len = length(near->xyz);
86595333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    *near /= len;
86695333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    len = length(far->xyz);
86795333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    *far /= len;
86895333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk}
86995333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk
870f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines__inline__ _RS_STATIC bool __attribute__((overloadable, always_inline))
87195333f998fd4a983f89e5128e85f6f710d200bd9Alex SakhartchoukrsIsSphereInFrustum(float4 *sphere,
87295333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk                      float4 *left, float4 *right,
87395333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk                      float4 *top, float4 *bottom,
87495333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk                      float4 *near, float4 *far) {
87595333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk
87695333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    float distToCenter = dot(left->xyz, sphere->xyz) + left->w;
877afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    if (distToCenter < -sphere->w) {
87895333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk        return false;
87995333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    }
88095333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    distToCenter = dot(right->xyz, sphere->xyz) + right->w;
881afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    if (distToCenter < -sphere->w) {
88295333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk        return false;
88395333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    }
88495333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    distToCenter = dot(top->xyz, sphere->xyz) + top->w;
885afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    if (distToCenter < -sphere->w) {
88695333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk        return false;
88795333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    }
88895333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    distToCenter = dot(bottom->xyz, sphere->xyz) + bottom->w;
889afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    if (distToCenter < -sphere->w) {
89095333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk        return false;
89195333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    }
89295333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    distToCenter = dot(near->xyz, sphere->xyz) + near->w;
893afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    if (distToCenter < -sphere->w) {
89495333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk        return false;
89595333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    }
89695333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    distToCenter = dot(far->xyz, sphere->xyz) + far->w;
897afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    if (distToCenter < -sphere->w) {
89895333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk        return false;
89995333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    }
90095333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk    return true;
90195333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk}
90295333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk
90320c6c1febce7cdf398c58287bf506b3a4a210285Alex Sakhartchouk
9047fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams/////////////////////////////////////////////////////
9057fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams// int ops
9067fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams/////////////////////////////////////////////////////
9077fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams
908f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines__inline__ _RS_STATIC uint __attribute__((overloadable, always_inline)) rsClamp(uint amount, uint low, uint high) {
9097fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    return amount < low ? low : (amount > high ? high : amount);
9107fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams}
911f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines__inline__ _RS_STATIC int __attribute__((overloadable, always_inline)) rsClamp(int amount, int low, int high) {
9127fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    return amount < low ? low : (amount > high ? high : amount);
9137fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams}
914f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines__inline__ _RS_STATIC ushort __attribute__((overloadable, always_inline)) rsClamp(ushort amount, ushort low, ushort high) {
9157fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    return amount < low ? low : (amount > high ? high : amount);
9167fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams}
917f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines__inline__ _RS_STATIC short __attribute__((overloadable, always_inline)) rsClamp(short amount, short low, short high) {
9187fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    return amount < low ? low : (amount > high ? high : amount);
9197fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams}
920f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines__inline__ _RS_STATIC uchar __attribute__((overloadable, always_inline)) rsClamp(uchar amount, uchar low, uchar high) {
9217fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    return amount < low ? low : (amount > high ? high : amount);
9227fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams}
923f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines__inline__ _RS_STATIC char __attribute__((overloadable, always_inline)) rsClamp(char amount, char low, char high) {
9247fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams    return amount < low ? low : (amount > high ? high : amount);
9257fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams}
9267fe6bce13c30b8d14dc833e06468666d28e56ee1Jason Sams
927f6a28c6a71d8929fb90ca83634a617d69531d87dStephen Hines#undef _RS_STATIC
928275b1e98bb949643d35546f10f8b1af009349526Jason Sams
929275b1e98bb949643d35546f10f8b1af009349526Jason Sams#endif
930275b1e98bb949643d35546f10f8b1af009349526Jason Sams
931