c48eff1bbe2ded3a6ada669569980a0121f8042f
[sdk] / ecere / src / gfx / drivers / gl3 / matrixStack.ec
1 // Matrix Stack Implementation
2
3 #ifndef _GLES
4 // #define SHADERS
5 #endif
6
7 #if !defined(__ANDROID__) && !defined(__EMSCRIPTEN__) && !defined(__ODROID__)
8 #  if defined(SHADERS)
9 #     include "gl_core_3_3.h"
10 #  else
11 #     include "gl_compat_4_4.h"
12 #  endif
13 #endif
14
15 import "Display"
16
17 #if defined(ECERE_NO3D) || defined(ECERE_VANILLA)
18 public union Matrix
19 {
20    double array[16];
21    double m[4][4];
22
23    void Identity()
24    {
25       FillBytesBy4(this, 0, sizeof(Matrix) >> 2);
26       m[0][0]=m[1][1]=m[2][2]=m[3][3]=1;
27    }
28
29    void Transpose(Matrix source)
30    {
31       int i,j;
32       for(i=0; i<4; i++)
33          for(j=0; j<4; j++)
34             m[j][i] = source.m[i][j];
35    }
36
37    void Multiply(Matrix a, Matrix b)
38    {
39       // We need a full matrix multiplication for the Projection matrix
40       m[0][0]=a.m[0][0]*b.m[0][0] + a.m[0][1]*b.m[1][0] + a.m[0][2]*b.m[2][0] + a.m[0][3]*b.m[3][0];
41       m[0][1]=a.m[0][0]*b.m[0][1] + a.m[0][1]*b.m[1][1] + a.m[0][2]*b.m[2][1] + a.m[0][3]*b.m[3][1];
42       m[0][2]=a.m[0][0]*b.m[0][2] + a.m[0][1]*b.m[1][2] + a.m[0][2]*b.m[2][2] + a.m[0][3]*b.m[3][2];
43       m[0][3]=a.m[0][0]*b.m[0][3] + a.m[0][1]*b.m[1][3] + a.m[0][2]*b.m[2][3] + a.m[0][3]*b.m[3][3];
44
45       m[1][0]=a.m[1][0]*b.m[0][0] + a.m[1][1]*b.m[1][0] + a.m[1][2]*b.m[2][0] + a.m[1][3]*b.m[3][0];
46       m[1][1]=a.m[1][0]*b.m[0][1] + a.m[1][1]*b.m[1][1] + a.m[1][2]*b.m[2][1] + a.m[1][3]*b.m[3][1];
47       m[1][2]=a.m[1][0]*b.m[0][2] + a.m[1][1]*b.m[1][2] + a.m[1][2]*b.m[2][2] + a.m[1][3]*b.m[3][2];
48       m[1][3]=a.m[1][0]*b.m[0][3] + a.m[1][1]*b.m[1][3] + a.m[1][2]*b.m[2][3] + a.m[1][3]*b.m[3][3];
49
50       m[2][0]=a.m[2][0]*b.m[0][0] + a.m[2][1]*b.m[1][0] + a.m[2][2]*b.m[2][0] + a.m[2][3]*b.m[3][0];
51       m[2][1]=a.m[2][0]*b.m[0][1] + a.m[2][1]*b.m[1][1] + a.m[2][2]*b.m[2][1] + a.m[2][3]*b.m[3][1];
52       m[2][2]=a.m[2][0]*b.m[0][2] + a.m[2][1]*b.m[1][2] + a.m[2][2]*b.m[2][2] + a.m[2][3]*b.m[3][2];
53       m[2][3]=a.m[2][0]*b.m[0][3] + a.m[2][1]*b.m[1][3] + a.m[2][2]*b.m[2][3] + a.m[2][3]*b.m[3][3];
54
55       m[3][0]=a.m[3][0]*b.m[0][0] + a.m[3][1]*b.m[1][0] + a.m[3][2]*b.m[2][0] + a.m[3][3]*b.m[3][0];
56       m[3][1]=a.m[3][0]*b.m[0][1] + a.m[3][1]*b.m[1][1] + a.m[3][2]*b.m[2][1] + a.m[3][3]*b.m[3][1];
57       m[3][2]=a.m[3][0]*b.m[0][2] + a.m[3][1]*b.m[1][2] + a.m[3][2]*b.m[2][2] + a.m[3][3]*b.m[3][2];
58       m[3][3]=a.m[3][0]*b.m[0][3] + a.m[3][1]*b.m[1][3] + a.m[3][2]*b.m[2][3] + a.m[3][3]*b.m[3][3];
59    }
60 };
61 #endif
62
63 public enum MatrixMode { modelView = 0x1700, projection = 0x1701, texture = 0x1702 };
64
65 double nearPlane = 1;
66
67 public double glmsGetNearPlane()
68 {
69    return nearPlane;
70 }
71
72 public void glmsSetNearPlane(double value)
73 {
74    nearPlane = value;
75 }
76
77 /*static */Matrix matrixStack[3][32];
78 /*static */int matrixIndex[3];
79 /*static */int curStack = 0;
80
81 static void LoadCurMatrix()
82 {
83    double * i = matrixStack[curStack][matrixIndex[curStack]].array;
84    float m[16] =
85    {
86       (float)i[0],(float)i[1],(float)i[2],(float)i[3],
87       (float)i[4],(float)i[5],(float)i[6],(float)i[7],
88       (float)i[8],(float)i[9],(float)i[10],(float)i[11],
89       (float)i[12],(float)i[13],(float)i[14],(float)i[15]
90    };
91
92 #ifdef SHADERS
93    shader_LoadMatrixf((MatrixMode) (0x1700 + curStack), m);
94 #else
95    glLoadMatrixf(m);
96 #endif
97 }
98
99 public void glmsLoadMatrix(Matrix matrix)
100 {
101    float m[16] =
102    {
103       (float)matrix.m[0][0], (float)matrix.m[0][1], (float)matrix.m[0][2], (float)matrix.m[0][3],
104       (float)matrix.m[1][0], (float)matrix.m[1][1], (float)matrix.m[1][2], (float)matrix.m[1][3],
105       (float)matrix.m[2][0], (float)matrix.m[2][1], (float)matrix.m[2][2], (float)matrix.m[2][3],
106       (float)matrix.m[3][0], (float)matrix.m[3][1], (float)matrix.m[3][2], (float)matrix.m[3][3]
107    };
108 #ifdef SHADERS
109       shader_LoadMatrixf((MatrixMode) (0x1700 + curStack), m);
110 #else
111       glLoadMatrixf(m);
112 #endif
113 }
114
115 public void glmsLoadIdentity()
116 {
117    matrixStack[curStack][matrixIndex[curStack]].Identity();
118    LoadCurMatrix();
119 }
120
121 public void glmsPushMatrix()
122 {
123    if(matrixIndex[curStack] + 1 < sizeof(matrixStack[0]) / sizeof(Matrix))
124    {
125       matrixIndex[curStack]++;
126       memcpy(matrixStack[curStack][matrixIndex[curStack]].array, matrixStack[curStack][matrixIndex[curStack]-1].array, sizeof(Matrix));
127    }
128 }
129
130 public void glmsPopMatrix()
131 {
132    if(matrixIndex[curStack] > 0)
133    {
134       matrixIndex[curStack]--;
135       LoadCurMatrix();
136    }
137 }
138
139 public void glmsLoadMatrixd(double * i)
140 {
141    memcpy(matrixStack[curStack][matrixIndex[curStack]].array, i, sizeof(Matrix));
142    LoadCurMatrix();
143 }
144
145 public void glmsOrtho( double l, double r, double b, double t, double n, double f )
146 {
147    Matrix m
148    { {
149       (2 / (r - l)), 0, 0, 0,
150       0, (2 / (t - b)), 0, 0,
151       0, 0, (-2 / (f - n)), 0,
152       (-(r + l) / (r - l)), (-(t + b) / (t - b)), (-(f + n) / (f - n)), 1
153    } };
154    Matrix res;
155    res.Multiply(m, matrixStack[curStack][matrixIndex[curStack]]);
156    matrixStack[curStack][matrixIndex[curStack]] = res;
157    LoadCurMatrix();
158 }
159
160 public void glmsFrustum( double l, double r, double b, double t, double n, double f )
161 {
162    nearPlane = n;
163    n = 1;
164    l /= nearPlane;
165    r /= nearPlane;
166    b /= nearPlane;
167    t /= nearPlane;
168    f /= nearPlane;
169    {
170       double A = ((r + l) / (r - l));
171       double B = ((t + b) / (t - b));
172       double C = (-(f + n) / (f - n));
173       double D = (-2*f*n/(f-n));
174       Matrix m
175       { {
176          (2.0*n / (r - l)), 0, 0, 0,
177          0, (2.0*n / (t - b)), 0, 0,
178          A, B,             C,-1,
179          0, 0,             D, 0
180       } };
181       Matrix res;
182       res.Multiply(m, matrixStack[curStack][matrixIndex[curStack]]);
183       matrixStack[curStack][matrixIndex[curStack]] = res;
184       LoadCurMatrix();
185    }
186 }
187
188 #if !defined(ECERE_NO3D) && !defined(ECERE_VANILLA)
189 public void glmsRotated( double a, double b, double c, double d )
190 {
191    Quaternion q;
192    Matrix m, r;
193
194    q.RotationAxis({(float)b,(float)c,(float)-d}, a );
195    m.RotationQuaternion(q);
196    r.Multiply(m, matrixStack[curStack][matrixIndex[curStack]]);
197    matrixStack[curStack][matrixIndex[curStack]] = r;
198    LoadCurMatrix();
199 }
200 public void glmsScaled( double a, double b, double c )
201 {
202    Matrix m, r;
203
204    m.Identity();
205    m.Scale(a,b,c);
206    r.Multiply(m, matrixStack[curStack][matrixIndex[curStack]]);
207    matrixStack[curStack][matrixIndex[curStack]] = r;
208    LoadCurMatrix();
209 }
210
211 public void glmsTranslated( double a, double b, double c )
212 {
213    Matrix m, r;
214
215    m.Identity();
216    m.Translate(a,b,c);
217    r.Multiply(m, matrixStack[curStack][matrixIndex[curStack]]);
218    matrixStack[curStack][matrixIndex[curStack]] = r;
219    LoadCurMatrix();
220 }
221
222 public void glmsMultMatrixd( double * i )
223 {
224    Matrix r;
225    r.Multiply((Matrix *)i, matrixStack[curStack][matrixIndex[curStack]]);
226    matrixStack[curStack][matrixIndex[curStack]] = r;
227    LoadCurMatrix();
228 }
229 #endif
230
231 public void glmsMatrixMode(MatrixMode mode)
232 {
233    curStack = (mode == modelView) ? 0 : (mode == projection) ? 1 : 2;
234 #ifndef SHADERS
235    glMatrixMode(mode);
236 #endif
237 }