Home | History | Annotate | Line # | Download | only in libutil
      1 /*
      2  * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
      3  * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
      4  *
      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:
     11  *
     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.
     16  *
     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.
     24  *
     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.
     29  */
     30 
     31 #include "gluos.h"
     32 #include <math.h>
     33 #include <GL/gl.h>
     34 #include <GL/glu.h>
     35 #include "gluint.h"
     36 
     37 /*
     38 ** Make m an identity matrix
     39 */
     40 static void __gluMakeIdentityd(GLdouble m[16])
     41 {
     42     m[0+4*0] = 1; m[0+4*1] = 0; m[0+4*2] = 0; m[0+4*3] = 0;
     43     m[1+4*0] = 0; m[1+4*1] = 1; m[1+4*2] = 0; m[1+4*3] = 0;
     44     m[2+4*0] = 0; m[2+4*1] = 0; m[2+4*2] = 1; m[2+4*3] = 0;
     45     m[3+4*0] = 0; m[3+4*1] = 0; m[3+4*2] = 0; m[3+4*3] = 1;
     46 }
     47 
     48 static void __gluMakeIdentityf(GLfloat m[16])
     49 {
     50     m[0+4*0] = 1; m[0+4*1] = 0; m[0+4*2] = 0; m[0+4*3] = 0;
     51     m[1+4*0] = 0; m[1+4*1] = 1; m[1+4*2] = 0; m[1+4*3] = 0;
     52     m[2+4*0] = 0; m[2+4*1] = 0; m[2+4*2] = 1; m[2+4*3] = 0;
     53     m[3+4*0] = 0; m[3+4*1] = 0; m[3+4*2] = 0; m[3+4*3] = 1;
     54 }
     55 
     56 void GLAPIENTRY
     57 gluOrtho2D(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top)
     58 {
     59     glOrtho(left, right, bottom, top, -1, 1);
     60 }
     61 
     62 #define __glPi 3.14159265358979323846
     63 
     64 void GLAPIENTRY
     65 gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar)
     66 {
     67     GLdouble m[4][4];
     68     double sine, cotangent, deltaZ;
     69     double radians = fovy / 2 * __glPi / 180;
     70 
     71     deltaZ = zFar - zNear;
     72     sine = sin(radians);
     73     if ((deltaZ == 0) || (sine == 0) || (aspect == 0)) {
     74 	return;
     75     }
     76     cotangent = COS(radians) / sine;
     77 
     78     __gluMakeIdentityd(&m[0][0]);
     79     m[0][0] = cotangent / aspect;
     80     m[1][1] = cotangent;
     81     m[2][2] = -(zFar + zNear) / deltaZ;
     82     m[2][3] = -1;
     83     m[3][2] = -2 * zNear * zFar / deltaZ;
     84     m[3][3] = 0;
     85     glMultMatrixd(&m[0][0]);
     86 }
     87 
     88 static void normalize(float v[3])
     89 {
     90     float r;
     91 
     92     r = sqrt( v[0]*v[0] + v[1]*v[1] + v[2]*v[2] );
     93     if (r == 0.0) return;
     94 
     95     v[0] /= r;
     96     v[1] /= r;
     97     v[2] /= r;
     98 }
     99 
    100 static void cross(float v1[3], float v2[3], float result[3])
    101 {
    102     result[0] = v1[1]*v2[2] - v1[2]*v2[1];
    103     result[1] = v1[2]*v2[0] - v1[0]*v2[2];
    104     result[2] = v1[0]*v2[1] - v1[1]*v2[0];
    105 }
    106 
    107 void GLAPIENTRY
    108 gluLookAt(GLdouble eyex, GLdouble eyey, GLdouble eyez, GLdouble centerx,
    109 	  GLdouble centery, GLdouble centerz, GLdouble upx, GLdouble upy,
    110 	  GLdouble upz)
    111 {
    112     float forward[3], side[3], up[3];
    113     GLfloat m[4][4];
    114 
    115     forward[0] = centerx - eyex;
    116     forward[1] = centery - eyey;
    117     forward[2] = centerz - eyez;
    118 
    119     up[0] = upx;
    120     up[1] = upy;
    121     up[2] = upz;
    122 
    123     normalize(forward);
    124 
    125     /* Side = forward x up */
    126     cross(forward, up, side);
    127     normalize(side);
    128 
    129     /* Recompute up as: up = side x forward */
    130     cross(side, forward, up);
    131 
    132     __gluMakeIdentityf(&m[0][0]);
    133     m[0][0] = side[0];
    134     m[1][0] = side[1];
    135     m[2][0] = side[2];
    136 
    137     m[0][1] = up[0];
    138     m[1][1] = up[1];
    139     m[2][1] = up[2];
    140 
    141     m[0][2] = -forward[0];
    142     m[1][2] = -forward[1];
    143     m[2][2] = -forward[2];
    144 
    145     glMultMatrixf(&m[0][0]);
    146     glTranslated(-eyex, -eyey, -eyez);
    147 }
    148 
    149 static void __gluMultMatrixVecd(const GLdouble matrix[16], const GLdouble in[4],
    150 		      GLdouble out[4])
    151 {
    152     int i;
    153 
    154     for (i=0; i<4; i++) {
    155 	out[i] =
    156 	    in[0] * matrix[0*4+i] +
    157 	    in[1] * matrix[1*4+i] +
    158 	    in[2] * matrix[2*4+i] +
    159 	    in[3] * matrix[3*4+i];
    160     }
    161 }
    162 
    163 /*
    164 ** Invert 4x4 matrix.
    165 ** Contributed by David Moore (See Mesa bug #6748)
    166 */
    167 static int __gluInvertMatrixd(const GLdouble m[16], GLdouble invOut[16])
    168 {
    169     double inv[16], det;
    170     int i;
    171 
    172     inv[0] =   m[5]*m[10]*m[15] - m[5]*m[11]*m[14] - m[9]*m[6]*m[15]
    173              + m[9]*m[7]*m[14] + m[13]*m[6]*m[11] - m[13]*m[7]*m[10];
    174     inv[4] =  -m[4]*m[10]*m[15] + m[4]*m[11]*m[14] + m[8]*m[6]*m[15]
    175              - m[8]*m[7]*m[14] - m[12]*m[6]*m[11] + m[12]*m[7]*m[10];
    176     inv[8] =   m[4]*m[9]*m[15] - m[4]*m[11]*m[13] - m[8]*m[5]*m[15]
    177              + m[8]*m[7]*m[13] + m[12]*m[5]*m[11] - m[12]*m[7]*m[9];
    178     inv[12] = -m[4]*m[9]*m[14] + m[4]*m[10]*m[13] + m[8]*m[5]*m[14]
    179              - m[8]*m[6]*m[13] - m[12]*m[5]*m[10] + m[12]*m[6]*m[9];
    180     inv[1] =  -m[1]*m[10]*m[15] + m[1]*m[11]*m[14] + m[9]*m[2]*m[15]
    181              - m[9]*m[3]*m[14] - m[13]*m[2]*m[11] + m[13]*m[3]*m[10];
    182     inv[5] =   m[0]*m[10]*m[15] - m[0]*m[11]*m[14] - m[8]*m[2]*m[15]
    183              + m[8]*m[3]*m[14] + m[12]*m[2]*m[11] - m[12]*m[3]*m[10];
    184     inv[9] =  -m[0]*m[9]*m[15] + m[0]*m[11]*m[13] + m[8]*m[1]*m[15]
    185              - m[8]*m[3]*m[13] - m[12]*m[1]*m[11] + m[12]*m[3]*m[9];
    186     inv[13] =  m[0]*m[9]*m[14] - m[0]*m[10]*m[13] - m[8]*m[1]*m[14]
    187              + m[8]*m[2]*m[13] + m[12]*m[1]*m[10] - m[12]*m[2]*m[9];
    188     inv[2] =   m[1]*m[6]*m[15] - m[1]*m[7]*m[14] - m[5]*m[2]*m[15]
    189              + m[5]*m[3]*m[14] + m[13]*m[2]*m[7] - m[13]*m[3]*m[6];
    190     inv[6] =  -m[0]*m[6]*m[15] + m[0]*m[7]*m[14] + m[4]*m[2]*m[15]
    191              - m[4]*m[3]*m[14] - m[12]*m[2]*m[7] + m[12]*m[3]*m[6];
    192     inv[10] =  m[0]*m[5]*m[15] - m[0]*m[7]*m[13] - m[4]*m[1]*m[15]
    193              + m[4]*m[3]*m[13] + m[12]*m[1]*m[7] - m[12]*m[3]*m[5];
    194     inv[14] = -m[0]*m[5]*m[14] + m[0]*m[6]*m[13] + m[4]*m[1]*m[14]
    195              - m[4]*m[2]*m[13] - m[12]*m[1]*m[6] + m[12]*m[2]*m[5];
    196     inv[3] =  -m[1]*m[6]*m[11] + m[1]*m[7]*m[10] + m[5]*m[2]*m[11]
    197              - m[5]*m[3]*m[10] - m[9]*m[2]*m[7] + m[9]*m[3]*m[6];
    198     inv[7] =   m[0]*m[6]*m[11] - m[0]*m[7]*m[10] - m[4]*m[2]*m[11]
    199              + m[4]*m[3]*m[10] + m[8]*m[2]*m[7] - m[8]*m[3]*m[6];
    200     inv[11] = -m[0]*m[5]*m[11] + m[0]*m[7]*m[9] + m[4]*m[1]*m[11]
    201              - m[4]*m[3]*m[9] - m[8]*m[1]*m[7] + m[8]*m[3]*m[5];
    202     inv[15] =  m[0]*m[5]*m[10] - m[0]*m[6]*m[9] - m[4]*m[1]*m[10]
    203              + m[4]*m[2]*m[9] + m[8]*m[1]*m[6] - m[8]*m[2]*m[5];
    204 
    205     det = m[0]*inv[0] + m[1]*inv[4] + m[2]*inv[8] + m[3]*inv[12];
    206     if (det == 0)
    207         return GL_FALSE;
    208 
    209     det = 1.0 / det;
    210 
    211     for (i = 0; i < 16; i++)
    212         invOut[i] = inv[i] * det;
    213 
    214     return GL_TRUE;
    215 }
    216 
    217 static void __gluMultMatricesd(const GLdouble a[16], const GLdouble b[16],
    218 				GLdouble r[16])
    219 {
    220     int i, j;
    221 
    222     for (i = 0; i < 4; i++) {
    223 	for (j = 0; j < 4; j++) {
    224 	    r[i*4+j] =
    225 		a[i*4+0]*b[0*4+j] +
    226 		a[i*4+1]*b[1*4+j] +
    227 		a[i*4+2]*b[2*4+j] +
    228 		a[i*4+3]*b[3*4+j];
    229 	}
    230     }
    231 }
    232 
    233 GLint GLAPIENTRY
    234 gluProject(GLdouble objx, GLdouble objy, GLdouble objz,
    235 	      const GLdouble modelMatrix[16],
    236 	      const GLdouble projMatrix[16],
    237               const GLint viewport[4],
    238 	      GLdouble *winx, GLdouble *winy, GLdouble *winz)
    239 {
    240     double in[4];
    241     double out[4];
    242 
    243     in[0]=objx;
    244     in[1]=objy;
    245     in[2]=objz;
    246     in[3]=1.0;
    247     __gluMultMatrixVecd(modelMatrix, in, out);
    248     __gluMultMatrixVecd(projMatrix, out, in);
    249     if (in[3] == 0.0) return(GL_FALSE);
    250     in[0] /= in[3];
    251     in[1] /= in[3];
    252     in[2] /= in[3];
    253     /* Map x, y and z to range 0-1 */
    254     in[0] = in[0] * 0.5 + 0.5;
    255     in[1] = in[1] * 0.5 + 0.5;
    256     in[2] = in[2] * 0.5 + 0.5;
    257 
    258     /* Map x,y to viewport */
    259     in[0] = in[0] * viewport[2] + viewport[0];
    260     in[1] = in[1] * viewport[3] + viewport[1];
    261 
    262     *winx=in[0];
    263     *winy=in[1];
    264     *winz=in[2];
    265     return(GL_TRUE);
    266 }
    267 
    268 GLint GLAPIENTRY
    269 gluUnProject(GLdouble winx, GLdouble winy, GLdouble winz,
    270 		const GLdouble modelMatrix[16],
    271 		const GLdouble projMatrix[16],
    272                 const GLint viewport[4],
    273 	        GLdouble *objx, GLdouble *objy, GLdouble *objz)
    274 {
    275     double finalMatrix[16];
    276     double in[4];
    277     double out[4];
    278 
    279     __gluMultMatricesd(modelMatrix, projMatrix, finalMatrix);
    280     if (!__gluInvertMatrixd(finalMatrix, finalMatrix)) return(GL_FALSE);
    281 
    282     in[0]=winx;
    283     in[1]=winy;
    284     in[2]=winz;
    285     in[3]=1.0;
    286 
    287     /* Map x and y from window coordinates */
    288     in[0] = (in[0] - viewport[0]) / viewport[2];
    289     in[1] = (in[1] - viewport[1]) / viewport[3];
    290 
    291     /* Map to range -1 to 1 */
    292     in[0] = in[0] * 2 - 1;
    293     in[1] = in[1] * 2 - 1;
    294     in[2] = in[2] * 2 - 1;
    295 
    296     __gluMultMatrixVecd(finalMatrix, in, out);
    297     if (out[3] == 0.0) return(GL_FALSE);
    298     out[0] /= out[3];
    299     out[1] /= out[3];
    300     out[2] /= out[3];
    301     *objx = out[0];
    302     *objy = out[1];
    303     *objz = out[2];
    304     return(GL_TRUE);
    305 }
    306 
    307 GLint GLAPIENTRY
    308 gluUnProject4(GLdouble winx, GLdouble winy, GLdouble winz, GLdouble clipw,
    309 	      const GLdouble modelMatrix[16],
    310 	      const GLdouble projMatrix[16],
    311 	      const GLint viewport[4],
    312 	      GLclampd nearVal, GLclampd farVal,
    313 	      GLdouble *objx, GLdouble *objy, GLdouble *objz,
    314 	      GLdouble *objw)
    315 {
    316     double finalMatrix[16];
    317     double in[4];
    318     double out[4];
    319 
    320     __gluMultMatricesd(modelMatrix, projMatrix, finalMatrix);
    321     if (!__gluInvertMatrixd(finalMatrix, finalMatrix)) return(GL_FALSE);
    322 
    323     in[0]=winx;
    324     in[1]=winy;
    325     in[2]=winz;
    326     in[3]=clipw;
    327 
    328     /* Map x and y from window coordinates */
    329     in[0] = (in[0] - viewport[0]) / viewport[2];
    330     in[1] = (in[1] - viewport[1]) / viewport[3];
    331     in[2] = (in[2] - nearVal) / (farVal - nearVal);
    332 
    333     /* Map to range -1 to 1 */
    334     in[0] = in[0] * 2 - 1;
    335     in[1] = in[1] * 2 - 1;
    336     in[2] = in[2] * 2 - 1;
    337 
    338     __gluMultMatrixVecd(finalMatrix, in, out);
    339     if (out[3] == 0.0) return(GL_FALSE);
    340     *objx = out[0];
    341     *objy = out[1];
    342     *objz = out[2];
    343     *objw = out[3];
    344     return(GL_TRUE);
    345 }
    346 
    347 void GLAPIENTRY
    348 gluPickMatrix(GLdouble x, GLdouble y, GLdouble deltax, GLdouble deltay,
    349 		  GLint viewport[4])
    350 {
    351     if (deltax <= 0 || deltay <= 0) {
    352 	return;
    353     }
    354 
    355     /* Translate and scale the picked region to the entire window */
    356     glTranslatef((viewport[2] - 2 * (x - viewport[0])) / deltax,
    357 	    (viewport[3] - 2 * (y - viewport[1])) / deltay, 0);
    358     glScalef(viewport[2] / deltax, viewport[3] / deltay, 1.0);
    359 }
    360