1 /*
2  *             Copyright Andrej Mitrovic 2013.
3  *  Distributed under the Boost Software License, Version 1.0.
4  *     (See accompanying file LICENSE_1_0.txt or copy at
5  *           http://www.boost.org/LICENSE_1_0.txt)
6  */
7 module demo.glu;
8 
9 import core.memory;
10 
11 import core.stdc.stdio;
12 import core.stdc.stdlib;
13 
14 import std.exception;
15 import std.math;
16 import std.random;
17 import std.stdio;
18 import std.string;
19 
20 alias stderr = std.stdio.stderr;
21 
22 import glad.gl.all;
23 import glad.gl.loader;
24 
25 /*
26 ** Make m an identity matrix
27 */
28 void __gluMakeIdentityd(ref GLdouble[16] m)
29 {
30     m[0 + 4 * 0] = 1;
31     m[0 + 4 * 1] = 0;
32     m[0 + 4 * 2] = 0;
33     m[0 + 4 * 3] = 0;
34     m[1 + 4 * 0] = 0;
35     m[1 + 4 * 1] = 1;
36     m[1 + 4 * 2] = 0;
37     m[1 + 4 * 3] = 0;
38     m[2 + 4 * 0] = 0;
39     m[2 + 4 * 1] = 0;
40     m[2 + 4 * 2] = 1;
41     m[2 + 4 * 3] = 0;
42     m[3 + 4 * 0] = 0;
43     m[3 + 4 * 1] = 0;
44     m[3 + 4 * 2] = 0;
45     m[3 + 4 * 3] = 1;
46 }
47 
48 /*
49 ** inverse = invert(src)
50 */
51 int __gluInvertMatrixd(ref GLdouble[16] src, ref GLdouble[16] inverse)
52 {
53     int i, j, k, swap;
54     double t = 0;
55     GLdouble[4][4] temp = 0;
56 
57     for (i = 0; i < 4; i++)
58     {
59         for (j = 0; j < 4; j++)
60         {
61             temp[i][j] = src[i * 4 + j];
62         }
63     }
64 
65     __gluMakeIdentityd(inverse);
66 
67     for (i = 0; i < 4; i++)
68     {
69         /*
70         ** Look for largest element in column
71         */
72         swap = i;
73 
74         for (j = i + 1; j < 4; j++)
75         {
76             if (fabs(temp[j][i]) > fabs(temp[i][i]))
77             {
78                 swap = j;
79             }
80         }
81 
82         if (swap != i)
83         {
84             /*
85             ** Swap rows.
86             */
87             for (k = 0; k < 4; k++)
88             {
89                 t = temp[i][k];
90                 temp[i][k]    = temp[swap][k];
91                 temp[swap][k] = t;
92 
93                 t = inverse[i * 4 + k];
94                 inverse[i * 4 + k]    = inverse[swap * 4 + k];
95                 inverse[swap * 4 + k] = t;
96             }
97         }
98 
99         if (temp[i][i] == 0)
100         {
101             /*
102             ** No non-zero pivot.  The matrix is singular, which shouldn't
103             ** happen.  This means the user gave us a bad matrix.
104             */
105             return GL_FALSE;
106         }
107 
108         t = temp[i][i];
109 
110         for (k = 0; k < 4; k++)
111         {
112             temp[i][k]         /= t;
113             inverse[i * 4 + k] /= t;
114         }
115 
116         for (j = 0; j < 4; j++)
117         {
118             if (j != i)
119             {
120                 t = temp[j][i];
121 
122                 for (k = 0; k < 4; k++)
123                 {
124                     temp[j][k]         -= temp[i][k] * t;
125                     inverse[j * 4 + k] -= inverse[i * 4 + k] * t;
126                 }
127             }
128         }
129     }
130 
131     return GL_TRUE;
132 }
133 
134 void __gluMultMatricesd(ref GLdouble[16] a, ref GLdouble[16] b, ref GLdouble[16] r)
135 {
136     int i, j;
137 
138     for (i = 0; i < 4; i++)
139     {
140         for (j = 0; j < 4; j++)
141         {
142             r[i * 4 + j] =
143                 a[i * 4 + 0] * b[0 * 4 + j] +
144                 a[i * 4 + 1] * b[1 * 4 + j] +
145                 a[i * 4 + 2] * b[2 * 4 + j] +
146                 a[i * 4 + 3] * b[3 * 4 + j];
147         }
148     }
149 }
150 
151 void __gluMultMatrixVecd(ref GLdouble[16] matrix, ref GLdouble[4] in_, ref GLdouble[4] out_)
152 {
153     int i;
154 
155     for (i = 0; i < 4; i++)
156     {
157         out_[i] =
158             in_[0] * matrix[0 * 4 + i] +
159             in_[1] * matrix[1 * 4 + i] +
160             in_[2] * matrix[2 * 4 + i] +
161             in_[3] * matrix[3 * 4 + i];
162     }
163 }
164 
165 GLint gluUnProject(ref GLdouble winx, GLdouble winy, GLdouble winz,
166                    ref GLdouble[16] modelMatrix,
167                    ref GLdouble[16] projMatrix,
168                    ref GLint[4] viewport,
169                    GLdouble* objx, GLdouble* objy, GLdouble* objz)
170 {
171     double[16] finalMatrix = 0;
172     double[4] in_ = 0;
173     double[4] out_ = 0;
174 
175     __gluMultMatricesd(modelMatrix, projMatrix, finalMatrix);
176 
177     if (!__gluInvertMatrixd(finalMatrix, finalMatrix))
178         return GL_FALSE;
179 
180     in_[0] = winx;
181     in_[1] = winy;
182     in_[2] = winz;
183     in_[3] = 1.0;
184 
185     /* Map x and y from window coordinates */
186     in_[0] = (in_[0] - viewport[0]) / viewport[2];
187     in_[1] = (in_[1] - viewport[1]) / viewport[3];
188 
189     /* Map to range -1 to 1 */
190     in_[0] = in_[0] * 2 - 1;
191     in_[1] = in_[1] * 2 - 1;
192     in_[2] = in_[2] * 2 - 1;
193 
194     __gluMultMatrixVecd(finalMatrix, in_, out_);
195 
196     if (out_[3] == 0.0)
197         return GL_FALSE;
198 
199     out_[0] /= out_[3];
200     out_[1] /= out_[3];
201     out_[2] /= out_[3];
202     *objx    = out_[0];
203     *objy    = out_[1];
204     *objz    = out_[2];
205 
206     return GL_TRUE;
207 }
208 
209 void gluOrtho2D(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top)
210 {
211     glOrtho(left, right, bottom, top, -1, 1);
212 }