include: Use the hard-float calling convention for Windows APIs on ARM
[wine.git] / dlls / glu32 / project.c
blob3db0331e96b5bca649b4ba2938584a80770bac44
1 /*
2 * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
3 * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice including the dates of first publication and
13 * either this permission notice or a reference to
14 * http://oss.sgi.com/projects/FreeB/
15 * shall be included in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
22 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
25 * Except as contained in this notice, the name of Silicon Graphics, Inc.
26 * shall not be used in advertising or otherwise to promote the sale, use or
27 * other dealings in this Software without prior written authorization from
28 * Silicon Graphics, Inc.
31 #include "config.h"
32 #include "wine/port.h"
34 #include <math.h>
36 #include "windef.h"
37 #include "wine/wgl.h"
38 #include "wine/glu.h"
41 ** Make m an identity matrix
43 static void __gluMakeIdentityd(GLdouble m[16])
45 m[0+4*0] = 1; m[0+4*1] = 0; m[0+4*2] = 0; m[0+4*3] = 0;
46 m[1+4*0] = 0; m[1+4*1] = 1; m[1+4*2] = 0; m[1+4*3] = 0;
47 m[2+4*0] = 0; m[2+4*1] = 0; m[2+4*2] = 1; m[2+4*3] = 0;
48 m[3+4*0] = 0; m[3+4*1] = 0; m[3+4*2] = 0; m[3+4*3] = 1;
51 static void __gluMakeIdentityf(GLfloat m[16])
53 m[0+4*0] = 1; m[0+4*1] = 0; m[0+4*2] = 0; m[0+4*3] = 0;
54 m[1+4*0] = 0; m[1+4*1] = 1; m[1+4*2] = 0; m[1+4*3] = 0;
55 m[2+4*0] = 0; m[2+4*1] = 0; m[2+4*2] = 1; m[2+4*3] = 0;
56 m[3+4*0] = 0; m[3+4*1] = 0; m[3+4*2] = 0; m[3+4*3] = 1;
59 /***********************************************************************
60 * gluOrtho2D (GLU32.@)
62 void WINAPI gluOrtho2D( GLdouble left, GLdouble right, GLdouble bottom, GLdouble top )
64 glOrtho(left, right, bottom, top, -1, 1);
67 /***********************************************************************
68 * gluPerspective (GLU32.@)
70 void WINAPI gluPerspective( GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar )
72 GLdouble m[4][4];
73 double sine, cotangent, deltaZ;
74 double radians = fovy / 2 * M_PI / 180;
76 deltaZ = zFar - zNear;
77 sine = sin(radians);
78 if ((deltaZ == 0) || (sine == 0) || (aspect == 0)) {
79 return;
81 cotangent = cos(radians) / sine;
83 __gluMakeIdentityd(&m[0][0]);
84 m[0][0] = cotangent / aspect;
85 m[1][1] = cotangent;
86 m[2][2] = -(zFar + zNear) / deltaZ;
87 m[2][3] = -1;
88 m[3][2] = -2 * zNear * zFar / deltaZ;
89 m[3][3] = 0;
90 glMultMatrixd(&m[0][0]);
93 static void normalize(float v[3])
95 float r;
97 r = sqrt( v[0]*v[0] + v[1]*v[1] + v[2]*v[2] );
98 if (r == 0.0) return;
100 v[0] /= r;
101 v[1] /= r;
102 v[2] /= r;
105 static void cross(float v1[3], float v2[3], float result[3])
107 result[0] = v1[1]*v2[2] - v1[2]*v2[1];
108 result[1] = v1[2]*v2[0] - v1[0]*v2[2];
109 result[2] = v1[0]*v2[1] - v1[1]*v2[0];
112 /***********************************************************************
113 * gluLookAt (GLU32.@)
115 void WINAPI gluLookAt( GLdouble eyex, GLdouble eyey, GLdouble eyez,
116 GLdouble centerx, GLdouble centery, GLdouble centerz,
117 GLdouble upx, GLdouble upy, GLdouble upz )
119 float forward[3], side[3], up[3];
120 GLfloat m[4][4];
122 forward[0] = centerx - eyex;
123 forward[1] = centery - eyey;
124 forward[2] = centerz - eyez;
126 up[0] = upx;
127 up[1] = upy;
128 up[2] = upz;
130 normalize(forward);
132 /* Side = forward x up */
133 cross(forward, up, side);
134 normalize(side);
136 /* Recompute up as: up = side x forward */
137 cross(side, forward, up);
139 __gluMakeIdentityf(&m[0][0]);
140 m[0][0] = side[0];
141 m[1][0] = side[1];
142 m[2][0] = side[2];
144 m[0][1] = up[0];
145 m[1][1] = up[1];
146 m[2][1] = up[2];
148 m[0][2] = -forward[0];
149 m[1][2] = -forward[1];
150 m[2][2] = -forward[2];
152 glMultMatrixf(&m[0][0]);
153 glTranslated(-eyex, -eyey, -eyez);
156 static void __gluMultMatrixVecd(const GLdouble matrix[16], const GLdouble in[4],
157 GLdouble out[4])
159 int i;
161 for (i=0; i<4; i++) {
162 out[i] =
163 in[0] * matrix[0*4+i] +
164 in[1] * matrix[1*4+i] +
165 in[2] * matrix[2*4+i] +
166 in[3] * matrix[3*4+i];
171 ** Invert 4x4 matrix.
172 ** Contributed by David Moore (See Mesa bug #6748)
174 static int __gluInvertMatrixd(const GLdouble m[16], GLdouble invOut[16])
176 double inv[16], det;
177 int i;
179 inv[0] = m[5]*m[10]*m[15] - m[5]*m[11]*m[14] - m[9]*m[6]*m[15]
180 + m[9]*m[7]*m[14] + m[13]*m[6]*m[11] - m[13]*m[7]*m[10];
181 inv[4] = -m[4]*m[10]*m[15] + m[4]*m[11]*m[14] + m[8]*m[6]*m[15]
182 - m[8]*m[7]*m[14] - m[12]*m[6]*m[11] + m[12]*m[7]*m[10];
183 inv[8] = m[4]*m[9]*m[15] - m[4]*m[11]*m[13] - m[8]*m[5]*m[15]
184 + m[8]*m[7]*m[13] + m[12]*m[5]*m[11] - m[12]*m[7]*m[9];
185 inv[12] = -m[4]*m[9]*m[14] + m[4]*m[10]*m[13] + m[8]*m[5]*m[14]
186 - m[8]*m[6]*m[13] - m[12]*m[5]*m[10] + m[12]*m[6]*m[9];
187 inv[1] = -m[1]*m[10]*m[15] + m[1]*m[11]*m[14] + m[9]*m[2]*m[15]
188 - m[9]*m[3]*m[14] - m[13]*m[2]*m[11] + m[13]*m[3]*m[10];
189 inv[5] = m[0]*m[10]*m[15] - m[0]*m[11]*m[14] - m[8]*m[2]*m[15]
190 + m[8]*m[3]*m[14] + m[12]*m[2]*m[11] - m[12]*m[3]*m[10];
191 inv[9] = -m[0]*m[9]*m[15] + m[0]*m[11]*m[13] + m[8]*m[1]*m[15]
192 - m[8]*m[3]*m[13] - m[12]*m[1]*m[11] + m[12]*m[3]*m[9];
193 inv[13] = m[0]*m[9]*m[14] - m[0]*m[10]*m[13] - m[8]*m[1]*m[14]
194 + m[8]*m[2]*m[13] + m[12]*m[1]*m[10] - m[12]*m[2]*m[9];
195 inv[2] = m[1]*m[6]*m[15] - m[1]*m[7]*m[14] - m[5]*m[2]*m[15]
196 + m[5]*m[3]*m[14] + m[13]*m[2]*m[7] - m[13]*m[3]*m[6];
197 inv[6] = -m[0]*m[6]*m[15] + m[0]*m[7]*m[14] + m[4]*m[2]*m[15]
198 - m[4]*m[3]*m[14] - m[12]*m[2]*m[7] + m[12]*m[3]*m[6];
199 inv[10] = m[0]*m[5]*m[15] - m[0]*m[7]*m[13] - m[4]*m[1]*m[15]
200 + m[4]*m[3]*m[13] + m[12]*m[1]*m[7] - m[12]*m[3]*m[5];
201 inv[14] = -m[0]*m[5]*m[14] + m[0]*m[6]*m[13] + m[4]*m[1]*m[14]
202 - m[4]*m[2]*m[13] - m[12]*m[1]*m[6] + m[12]*m[2]*m[5];
203 inv[3] = -m[1]*m[6]*m[11] + m[1]*m[7]*m[10] + m[5]*m[2]*m[11]
204 - m[5]*m[3]*m[10] - m[9]*m[2]*m[7] + m[9]*m[3]*m[6];
205 inv[7] = m[0]*m[6]*m[11] - m[0]*m[7]*m[10] - m[4]*m[2]*m[11]
206 + m[4]*m[3]*m[10] + m[8]*m[2]*m[7] - m[8]*m[3]*m[6];
207 inv[11] = -m[0]*m[5]*m[11] + m[0]*m[7]*m[9] + m[4]*m[1]*m[11]
208 - m[4]*m[3]*m[9] - m[8]*m[1]*m[7] + m[8]*m[3]*m[5];
209 inv[15] = m[0]*m[5]*m[10] - m[0]*m[6]*m[9] - m[4]*m[1]*m[10]
210 + m[4]*m[2]*m[9] + m[8]*m[1]*m[6] - m[8]*m[2]*m[5];
212 det = m[0]*inv[0] + m[1]*inv[4] + m[2]*inv[8] + m[3]*inv[12];
213 if (det == 0)
214 return GL_FALSE;
216 det = 1.0 / det;
218 for (i = 0; i < 16; i++)
219 invOut[i] = inv[i] * det;
221 return GL_TRUE;
224 static void __gluMultMatricesd(const GLdouble a[16], const GLdouble b[16],
225 GLdouble r[16])
227 int i, j;
229 for (i = 0; i < 4; i++) {
230 for (j = 0; j < 4; j++) {
231 r[i*4+j] =
232 a[i*4+0]*b[0*4+j] +
233 a[i*4+1]*b[1*4+j] +
234 a[i*4+2]*b[2*4+j] +
235 a[i*4+3]*b[3*4+j];
240 /***********************************************************************
241 * gluProject (GLU32.@)
243 GLint WINAPI gluProject( GLdouble objx, GLdouble objy, GLdouble objz, const GLdouble modelMatrix[16],
244 const GLdouble projMatrix[16], const GLint viewport[4],
245 GLdouble *winx, GLdouble *winy, GLdouble *winz )
247 double in[4];
248 double out[4];
250 in[0]=objx;
251 in[1]=objy;
252 in[2]=objz;
253 in[3]=1.0;
254 __gluMultMatrixVecd(modelMatrix, in, out);
255 __gluMultMatrixVecd(projMatrix, out, in);
256 if (in[3] == 0.0) return(GL_FALSE);
257 in[0] /= in[3];
258 in[1] /= in[3];
259 in[2] /= in[3];
260 /* Map x, y and z to range 0-1 */
261 in[0] = in[0] * 0.5 + 0.5;
262 in[1] = in[1] * 0.5 + 0.5;
263 in[2] = in[2] * 0.5 + 0.5;
265 /* Map x,y to viewport */
266 in[0] = in[0] * viewport[2] + viewport[0];
267 in[1] = in[1] * viewport[3] + viewport[1];
269 *winx=in[0];
270 *winy=in[1];
271 *winz=in[2];
272 return(GL_TRUE);
275 /***********************************************************************
276 * gluUnProject (GLU32.@)
278 GLint WINAPI gluUnProject( GLdouble winx, GLdouble winy, GLdouble winz, const GLdouble modelMatrix[16],
279 const GLdouble projMatrix[16], const GLint viewport[4],
280 GLdouble *objx, GLdouble *objy, GLdouble *objz )
282 double finalMatrix[16];
283 double in[4];
284 double out[4];
286 __gluMultMatricesd(modelMatrix, projMatrix, finalMatrix);
287 if (!__gluInvertMatrixd(finalMatrix, finalMatrix)) return(GL_FALSE);
289 in[0]=winx;
290 in[1]=winy;
291 in[2]=winz;
292 in[3]=1.0;
294 /* Map x and y from window coordinates */
295 in[0] = (in[0] - viewport[0]) / viewport[2];
296 in[1] = (in[1] - viewport[1]) / viewport[3];
298 /* Map to range -1 to 1 */
299 in[0] = in[0] * 2 - 1;
300 in[1] = in[1] * 2 - 1;
301 in[2] = in[2] * 2 - 1;
303 __gluMultMatrixVecd(finalMatrix, in, out);
304 if (out[3] == 0.0) return(GL_FALSE);
305 out[0] /= out[3];
306 out[1] /= out[3];
307 out[2] /= out[3];
308 *objx = out[0];
309 *objy = out[1];
310 *objz = out[2];
311 return(GL_TRUE);
314 /***********************************************************************
315 * gluPickMatrix (GLU32.@)
317 void WINAPI gluPickMatrix( GLdouble x, GLdouble y, GLdouble deltax, GLdouble deltay, GLint viewport[4] )
319 if (deltax <= 0 || deltay <= 0) {
320 return;
323 /* Translate and scale the picked region to the entire window */
324 glTranslatef((viewport[2] - 2 * (x - viewport[0])) / deltax,
325 (viewport[3] - 2 * (y - viewport[1])) / deltay, 0);
326 glScalef(viewport[2] / deltax, viewport[3] / deltay, 1.0);