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