shapes demo can now test shader based drawing as well, added glmatrix
[freeglut] / progs / demos / shapes / glmatrix.c
1 #include <string.h>\r
2 #define _USE_MATH_DEFINES\r
3 #include <math.h>\r
4 #include "glmatrix.h"\r
5 \r
6 #define MMODE_IDX(x)    ((x) - GL_MODELVIEW)\r
7 #define MAT_STACK_SIZE  32\r
8 #define MAT_IDENT       {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}\r
9 \r
10 static int mm_idx = 0;\r
11 static float mat_stack[3][MAT_STACK_SIZE][16] = {{MAT_IDENT}, {MAT_IDENT}, {MAT_IDENT}};\r
12 static int stack_top[3];\r
13 \r
14 void gl_matrix_mode(int mm)\r
15 {\r
16     mm_idx = MMODE_IDX(mm);\r
17 }\r
18 \r
19 void gl_push_matrix(void)\r
20 {\r
21     int top = stack_top[mm_idx];\r
22 \r
23     memcpy(mat_stack[mm_idx][top + 1], mat_stack[mm_idx][top], 16 * sizeof(float));\r
24     stack_top[mm_idx]++;\r
25 }\r
26 \r
27 void gl_pop_matrix(void)\r
28 {\r
29     stack_top[mm_idx]--;\r
30 }\r
31 \r
32 void gl_load_identity(void)\r
33 {\r
34     static const float idmat[] = MAT_IDENT;\r
35     int top = stack_top[mm_idx];\r
36     float *mat = mat_stack[mm_idx][top];\r
37 \r
38     memcpy(mat, idmat, sizeof idmat);\r
39 }\r
40 \r
41 void gl_load_matrixf(const float *m)\r
42 {\r
43     int top = stack_top[mm_idx];\r
44     float *mat = mat_stack[mm_idx][top];\r
45 \r
46     memcpy(mat, m, 16 * sizeof *mat);\r
47 }\r
48 \r
49 #define M4(i, j)        ((i << 2) + j)\r
50 \r
51 void gl_mult_matrixf(const float *m2)\r
52 {\r
53     int i, j;\r
54     int top = stack_top[mm_idx];\r
55     float *m1 = mat_stack[mm_idx][top];\r
56     float res[16];\r
57 \r
58     for(i=0; i<4; i++) {\r
59         for(j=0; j<4; j++) {\r
60             res[M4(i,j)] = m1[M4(i,0)] * m2[M4(0,j)] +\r
61                         m1[M4(i,1)] * m2[M4(1,j)] +\r
62                         m1[M4(i,2)] * m2[M4(2,j)] +\r
63                         m1[M4(i,3)] * m2[M4(3,j)];\r
64         }\r
65     }\r
66 \r
67     memcpy(m1, res, sizeof res);\r
68 }\r
69 \r
70 void gl_translatef(float x, float y, float z)\r
71 {\r
72     float mat[] = MAT_IDENT;\r
73 \r
74     mat[12] = x;\r
75     mat[13] = y;\r
76     mat[14] = z;\r
77 \r
78     gl_mult_matrixf(mat);\r
79 }\r
80 \r
81 void gl_rotatef(float angle, float x, float y, float z)\r
82 {\r
83     float mat[] = MAT_IDENT;\r
84 \r
85     float angle_rad = (float)M_PI * angle / 180.f;\r
86     float sina = (float)sin(angle_rad);\r
87     float cosa = (float)cos(angle_rad);\r
88     float one_minus_cosa = 1.f - cosa;\r
89     float nxsq = x * x;\r
90     float nysq = y * y;\r
91     float nzsq = z * z;\r
92 \r
93     mat[0] = nxsq + (1.f - nxsq) * cosa;\r
94     mat[4] = x * y * one_minus_cosa - z * sina;\r
95     mat[8] = x * z * one_minus_cosa + y * sina;\r
96     mat[1] = x * y * one_minus_cosa + z * sina;\r
97     mat[5] = nysq + (1.f - nysq) * cosa;\r
98     mat[9] = y * z * one_minus_cosa - x * sina;\r
99     mat[2] = x * z * one_minus_cosa - y * sina;\r
100     mat[6] = y * z * one_minus_cosa + x * sina;\r
101     mat[10] = nzsq + (1.f - nzsq) * cosa;\r
102 \r
103     gl_mult_matrixf(mat);\r
104 }\r
105 \r
106 void gl_scalef(float x, float y, float z)\r
107 {\r
108     float mat[] = MAT_IDENT;\r
109 \r
110     mat[0] = x;\r
111     mat[5] = y;\r
112     mat[10] = z;\r
113 \r
114     gl_mult_matrixf(mat);\r
115 }\r
116 \r
117 void gl_ortho(float left, float right, float bottom, float top, float near, float far)\r
118 {\r
119     float mat[] = MAT_IDENT;\r
120 \r
121     float dx = right - left;\r
122     float dy = top - bottom;\r
123     float dz = far - near;\r
124 \r
125     float tx = -(right + left) / dx;\r
126     float ty = -(top + bottom) / dy;\r
127     float tz = -(far + near) / dz;\r
128 \r
129     float sx = 2.f / dx;\r
130     float sy = 2.f / dy;\r
131     float sz = -2.f / dz;\r
132 \r
133     mat[0] = sx;\r
134     mat[5] = sy;\r
135     mat[10] = sz;\r
136     mat[12] = tx;\r
137     mat[13] = ty;\r
138     mat[14] = tz;\r
139 \r
140     gl_mult_matrixf(mat);\r
141 }\r
142 \r
143 void gl_frustum(float left, float right, float bottom, float top, float near, float far)\r
144 {\r
145     float mat[] = MAT_IDENT;\r
146 \r
147     float dx = right - left;\r
148     float dy = top - bottom;\r
149     float dz = far - near;\r
150 \r
151     float a = (right + left) / dx;\r
152     float b = (top + bottom) / dy;\r
153     float c = -(far + near) / dz;\r
154     float d = -2.f * far * near / dz;\r
155 \r
156     mat[0] = 2.f * near / dx;\r
157     mat[5] = 2.f * near / dy;\r
158     mat[8] = a;\r
159     mat[9] = b;\r
160     mat[10] = c;\r
161     mat[11] = -1.f;\r
162     mat[14] = d;\r
163 \r
164     gl_mult_matrixf(mat);\r
165 }\r
166 \r
167 void glu_perspective(float vfov, float aspect, float near, float far)\r
168 {\r
169     float vfov_rad = (float)M_PI * vfov / 180.f;\r
170     float x = near * (float)tan(vfov_rad / 2.f);\r
171     gl_frustum(-aspect * x, aspect * x, -x, x, near, far);\r
172 }\r
173 \r
174 float* get_matrix(int mm)\r
175 {\r
176     int idx = MMODE_IDX(mm);\r
177     int top = stack_top[idx];\r
178     return mat_stack[idx][top];\r
179 }\r
180 \r
181 \r
182 #define M3(i, j)        ((i * 3) + j)\r
183 static float inv_transpose_result[9];\r
184 \r
185 float* get_inv_transpose_3x3(int mm)\r
186 {\r
187     int idx = MMODE_IDX(mm);\r
188     int top = stack_top[idx];\r
189     float *m1 = mat_stack[idx][top];\r
190     \r
191 \r
192     float determinant = +m1[M4(0,0)]*(m1[M4(1,1)]*m1[M4(2,2)]-m1[M4(2,1)]*m1[M4(1,2)])\r
193                         -m1[M4(0,1)]*(m1[M4(1,0)]*m1[M4(2,2)]-m1[M4(1,2)]*m1[M4(2,0)])\r
194                         +m1[M4(0,2)]*(m1[M4(1,0)]*m1[M4(2,1)]-m1[M4(1,1)]*m1[M4(2,0)]);\r
195 \r
196     float invdet = 1/determinant;\r
197 \r
198     inv_transpose_result[M3(0,0)] =  (m1[M4(1,1)]*m1[M4(2,2)]-m1[M4(2,1)]*m1[M4(1,2)])*invdet;\r
199     inv_transpose_result[M3(1,0)] = -(m1[M4(0,1)]*m1[M4(2,2)]-m1[M4(0,2)]*m1[M4(2,1)])*invdet;\r
200     inv_transpose_result[M3(2,0)] =  (m1[M4(0,1)]*m1[M4(1,2)]-m1[M4(0,2)]*m1[M4(1,1)])*invdet;\r
201     inv_transpose_result[M3(0,1)] = -(m1[M4(1,0)]*m1[M4(2,2)]-m1[M4(1,2)]*m1[M4(2,0)])*invdet;\r
202     inv_transpose_result[M3(1,1)] =  (m1[M4(0,0)]*m1[M4(2,2)]-m1[M4(0,2)]*m1[M4(2,0)])*invdet;\r
203     inv_transpose_result[M3(2,1)] = -(m1[M4(0,0)]*m1[M4(1,2)]-m1[M4(1,0)]*m1[M4(0,2)])*invdet;\r
204     inv_transpose_result[M3(0,2)] =  (m1[M4(1,0)]*m1[M4(2,1)]-m1[M4(2,0)]*m1[M4(1,1)])*invdet;\r
205     inv_transpose_result[M3(1,2)] = -(m1[M4(0,0)]*m1[M4(2,1)]-m1[M4(2,0)]*m1[M4(0,1)])*invdet;\r
206     inv_transpose_result[M3(2,2)] =  (m1[M4(0,0)]*m1[M4(1,1)]-m1[M4(1,0)]*m1[M4(0,1)])*invdet;\r
207 \r
208     return inv_transpose_result;\r
209 }\r
210 \r
211 \r
212 #if 0\r
213 void gl_apply_xform(unsigned int prog)\r
214 {\r
215     int loc, mvidx, pidx, tidx, mvtop, ptop, ttop;\r
216 \r
217     mvidx = MMODE_IDX(GL_MODELVIEW);\r
218     pidx = MMODE_IDX(GL_PROJECTION);\r
219     tidx = MMODE_IDX(GL_TEXTURE);\r
220 \r
221     mvtop = stack_top[mvidx];\r
222     ptop = stack_top[pidx];\r
223     ttop = stack_top[tidx];\r
224 \r
225     assert(prog);\r
226 \r
227     if((loc = glGetUniformLocation(prog, "matrix_modelview")) != -1) {\r
228         glUniformMatrix4fv(loc, 1, 0, mat_stack[mvidx][mvtop]);\r
229     }\r
230 \r
231     if((loc = glGetUniformLocation(prog, "matrix_projection")) != -1) {\r
232         glUniformMatrix4fv(loc, 1, 0, mat_stack[pidx][ptop]);\r
233     }\r
234 \r
235     if((loc = glGetUniformLocation(prog, "matrix_texture")) != -1) {\r
236         glUniformMatrix4fv(loc, 1, 0, mat_stack[tidx][ttop]);\r
237     }\r
238 \r
239     if((loc = glGetUniformLocation(prog, "matrix_normal")) != -1) {\r
240         float nmat[9];\r
241 \r
242         nmat[0] = mat_stack[mvidx][mvtop][0];\r
243         nmat[1] = mat_stack[mvidx][mvtop][1];\r
244         nmat[2] = mat_stack[mvidx][mvtop][2];\r
245         nmat[3] = mat_stack[mvidx][mvtop][4];\r
246         nmat[4] = mat_stack[mvidx][mvtop][5];\r
247         nmat[5] = mat_stack[mvidx][mvtop][6];\r
248         nmat[6] = mat_stack[mvidx][mvtop][8];\r
249         nmat[7] = mat_stack[mvidx][mvtop][9];\r
250         nmat[8] = mat_stack[mvidx][mvtop][10];\r
251         glUniformMatrix3fv(loc, 1, 0, nmat);\r
252     }\r
253 }\r
254 #endif\r