mirror of
https://github.com/QB64-Phoenix-Edition/QB64pe.git
synced 2024-09-19 16:45:06 +00:00
379 lines
11 KiB
C
379 lines
11 KiB
C
|
/*
|
||
|
* SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
|
||
|
* Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
|
||
|
*
|
||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||
|
* copy of this software and associated documentation files (the "Software"),
|
||
|
* to deal in the Software without restriction, including without limitation
|
||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||
|
* Software is furnished to do so, subject to the following conditions:
|
||
|
*
|
||
|
* The above copyright notice including the dates of first publication and
|
||
|
* either this permission notice or a reference to
|
||
|
* http://oss.sgi.com/projects/FreeB/
|
||
|
* shall be included in all copies or substantial portions of the Software.
|
||
|
*
|
||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||
|
* SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
|
||
|
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||
|
* SOFTWARE.
|
||
|
*
|
||
|
* Except as contained in this notice, the name of Silicon Graphics, Inc.
|
||
|
* shall not be used in advertising or otherwise to promote the sale, use or
|
||
|
* other dealings in this Software without prior written authorization from
|
||
|
* Silicon Graphics, Inc.
|
||
|
*
|
||
|
* OpenGL ES 1.0 CM port of part of GLU by Mike Gorchak <mike@malva.ua>
|
||
|
*/
|
||
|
|
||
|
#include <math.h>
|
||
|
#include "glues_project.h"
|
||
|
|
||
|
/*
|
||
|
** Make m an identity matrix
|
||
|
*/
|
||
|
|
||
|
static void __gluMakeIdentityf(GLfloat m[16])
|
||
|
{
|
||
|
m[0+4*0] = 1; m[0+4*1] = 0; m[0+4*2] = 0; m[0+4*3] = 0;
|
||
|
m[1+4*0] = 0; m[1+4*1] = 1; m[1+4*2] = 0; m[1+4*3] = 0;
|
||
|
m[2+4*0] = 0; m[2+4*1] = 0; m[2+4*2] = 1; m[2+4*3] = 0;
|
||
|
m[3+4*0] = 0; m[3+4*1] = 0; m[3+4*2] = 0; m[3+4*3] = 1;
|
||
|
}
|
||
|
|
||
|
GLAPI void APIENTRY
|
||
|
gluOrtho2D(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top)
|
||
|
{
|
||
|
glOrthof(left, right, bottom, top, -1, 1);
|
||
|
}
|
||
|
|
||
|
#define __glPi 3.14159265358979323846
|
||
|
|
||
|
GLAPI void APIENTRY
|
||
|
gluPerspective(GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar)
|
||
|
{
|
||
|
GLfloat m[4][4];
|
||
|
GLfloat sine, cotangent, deltaZ;
|
||
|
GLfloat radians=(GLfloat)(fovy/2.0f*__glPi/180.0f);
|
||
|
|
||
|
deltaZ=zFar-zNear;
|
||
|
sine=(GLfloat)sin(radians);
|
||
|
if ((deltaZ==0.0f) || (sine==0.0f) || (aspect==0.0f))
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
cotangent=(GLfloat)(cos(radians)/sine);
|
||
|
|
||
|
__gluMakeIdentityf(&m[0][0]);
|
||
|
m[0][0] = cotangent / aspect;
|
||
|
m[1][1] = cotangent;
|
||
|
m[2][2] = -(zFar + zNear) / deltaZ;
|
||
|
m[2][3] = -1.0f;
|
||
|
m[3][2] = -2.0f * zNear * zFar / deltaZ;
|
||
|
m[3][3] = 0;
|
||
|
glMultMatrixf(&m[0][0]);
|
||
|
}
|
||
|
|
||
|
static void normalize(GLfloat v[3])
|
||
|
{
|
||
|
GLfloat r;
|
||
|
|
||
|
r=(GLfloat)sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
|
||
|
if (r==0.0f)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
v[0]/=r;
|
||
|
v[1]/=r;
|
||
|
v[2]/=r;
|
||
|
}
|
||
|
|
||
|
static void cross(GLfloat v1[3], GLfloat v2[3], GLfloat result[3])
|
||
|
{
|
||
|
result[0] = v1[1]*v2[2] - v1[2]*v2[1];
|
||
|
result[1] = v1[2]*v2[0] - v1[0]*v2[2];
|
||
|
result[2] = v1[0]*v2[1] - v1[1]*v2[0];
|
||
|
}
|
||
|
|
||
|
GLAPI void APIENTRY
|
||
|
gluLookAt(GLfloat eyex, GLfloat eyey, GLfloat eyez, GLfloat centerx,
|
||
|
GLfloat centery, GLfloat centerz, GLfloat upx, GLfloat upy,
|
||
|
GLfloat upz)
|
||
|
{
|
||
|
GLfloat forward[3], side[3], up[3];
|
||
|
GLfloat m[4][4];
|
||
|
|
||
|
forward[0] = centerx - eyex;
|
||
|
forward[1] = centery - eyey;
|
||
|
forward[2] = centerz - eyez;
|
||
|
|
||
|
up[0] = upx;
|
||
|
up[1] = upy;
|
||
|
up[2] = upz;
|
||
|
|
||
|
normalize(forward);
|
||
|
|
||
|
/* Side = forward x up */
|
||
|
cross(forward, up, side);
|
||
|
normalize(side);
|
||
|
|
||
|
/* Recompute up as: up = side x forward */
|
||
|
cross(side, forward, up);
|
||
|
|
||
|
__gluMakeIdentityf(&m[0][0]);
|
||
|
m[0][0] = side[0];
|
||
|
m[1][0] = side[1];
|
||
|
m[2][0] = side[2];
|
||
|
|
||
|
m[0][1] = up[0];
|
||
|
m[1][1] = up[1];
|
||
|
m[2][1] = up[2];
|
||
|
|
||
|
m[0][2] = -forward[0];
|
||
|
m[1][2] = -forward[1];
|
||
|
m[2][2] = -forward[2];
|
||
|
|
||
|
glMultMatrixf(&m[0][0]);
|
||
|
glTranslatef(-eyex, -eyey, -eyez);
|
||
|
}
|
||
|
|
||
|
static void __gluMultMatrixVecf(const GLfloat matrix[16], const GLfloat in[4],
|
||
|
GLfloat out[4])
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
for (i=0; i<4; i++)
|
||
|
{
|
||
|
out[i] = in[0] * matrix[0*4+i] +
|
||
|
in[1] * matrix[1*4+i] +
|
||
|
in[2] * matrix[2*4+i] +
|
||
|
in[3] * matrix[3*4+i];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** Invert 4x4 matrix.
|
||
|
** Contributed by David Moore (See Mesa bug #6748)
|
||
|
*/
|
||
|
static int __gluInvertMatrixf(const GLfloat m[16], GLfloat invOut[16])
|
||
|
{
|
||
|
GLfloat inv[16], det;
|
||
|
int i;
|
||
|
|
||
|
inv[0] = m[5]*m[10]*m[15] - m[5]*m[11]*m[14] - m[9]*m[6]*m[15]
|
||
|
+ m[9]*m[7]*m[14] + m[13]*m[6]*m[11] - m[13]*m[7]*m[10];
|
||
|
inv[4] = -m[4]*m[10]*m[15] + m[4]*m[11]*m[14] + m[8]*m[6]*m[15]
|
||
|
- m[8]*m[7]*m[14] - m[12]*m[6]*m[11] + m[12]*m[7]*m[10];
|
||
|
inv[8] = m[4]*m[9]*m[15] - m[4]*m[11]*m[13] - m[8]*m[5]*m[15]
|
||
|
+ m[8]*m[7]*m[13] + m[12]*m[5]*m[11] - m[12]*m[7]*m[9];
|
||
|
inv[12] = -m[4]*m[9]*m[14] + m[4]*m[10]*m[13] + m[8]*m[5]*m[14]
|
||
|
- m[8]*m[6]*m[13] - m[12]*m[5]*m[10] + m[12]*m[6]*m[9];
|
||
|
inv[1] = -m[1]*m[10]*m[15] + m[1]*m[11]*m[14] + m[9]*m[2]*m[15]
|
||
|
- m[9]*m[3]*m[14] - m[13]*m[2]*m[11] + m[13]*m[3]*m[10];
|
||
|
inv[5] = m[0]*m[10]*m[15] - m[0]*m[11]*m[14] - m[8]*m[2]*m[15]
|
||
|
+ m[8]*m[3]*m[14] + m[12]*m[2]*m[11] - m[12]*m[3]*m[10];
|
||
|
inv[9] = -m[0]*m[9]*m[15] + m[0]*m[11]*m[13] + m[8]*m[1]*m[15]
|
||
|
- m[8]*m[3]*m[13] - m[12]*m[1]*m[11] + m[12]*m[3]*m[9];
|
||
|
inv[13] = m[0]*m[9]*m[14] - m[0]*m[10]*m[13] - m[8]*m[1]*m[14]
|
||
|
+ m[8]*m[2]*m[13] + m[12]*m[1]*m[10] - m[12]*m[2]*m[9];
|
||
|
inv[2] = m[1]*m[6]*m[15] - m[1]*m[7]*m[14] - m[5]*m[2]*m[15]
|
||
|
+ m[5]*m[3]*m[14] + m[13]*m[2]*m[7] - m[13]*m[3]*m[6];
|
||
|
inv[6] = -m[0]*m[6]*m[15] + m[0]*m[7]*m[14] + m[4]*m[2]*m[15]
|
||
|
- m[4]*m[3]*m[14] - m[12]*m[2]*m[7] + m[12]*m[3]*m[6];
|
||
|
inv[10] = m[0]*m[5]*m[15] - m[0]*m[7]*m[13] - m[4]*m[1]*m[15]
|
||
|
+ m[4]*m[3]*m[13] + m[12]*m[1]*m[7] - m[12]*m[3]*m[5];
|
||
|
inv[14] = -m[0]*m[5]*m[14] + m[0]*m[6]*m[13] + m[4]*m[1]*m[14]
|
||
|
- m[4]*m[2]*m[13] - m[12]*m[1]*m[6] + m[12]*m[2]*m[5];
|
||
|
inv[3] = -m[1]*m[6]*m[11] + m[1]*m[7]*m[10] + m[5]*m[2]*m[11]
|
||
|
- m[5]*m[3]*m[10] - m[9]*m[2]*m[7] + m[9]*m[3]*m[6];
|
||
|
inv[7] = m[0]*m[6]*m[11] - m[0]*m[7]*m[10] - m[4]*m[2]*m[11]
|
||
|
+ m[4]*m[3]*m[10] + m[8]*m[2]*m[7] - m[8]*m[3]*m[6];
|
||
|
inv[11] = -m[0]*m[5]*m[11] + m[0]*m[7]*m[9] + m[4]*m[1]*m[11]
|
||
|
- m[4]*m[3]*m[9] - m[8]*m[1]*m[7] + m[8]*m[3]*m[5];
|
||
|
inv[15] = m[0]*m[5]*m[10] - m[0]*m[6]*m[9] - m[4]*m[1]*m[10]
|
||
|
+ m[4]*m[2]*m[9] + m[8]*m[1]*m[6] - m[8]*m[2]*m[5];
|
||
|
|
||
|
det = m[0]*inv[0] + m[1]*inv[4] + m[2]*inv[8] + m[3]*inv[12];
|
||
|
if (det == 0)
|
||
|
return GL_FALSE;
|
||
|
|
||
|
det=1.0f/det;
|
||
|
|
||
|
for (i = 0; i < 16; i++)
|
||
|
invOut[i] = inv[i] * det;
|
||
|
|
||
|
return GL_TRUE;
|
||
|
}
|
||
|
|
||
|
static void __gluMultMatricesf(const GLfloat a[16], const GLfloat b[16],
|
||
|
GLfloat r[16])
|
||
|
{
|
||
|
int i, j;
|
||
|
|
||
|
for (i = 0; i < 4; i++)
|
||
|
{
|
||
|
for (j = 0; j < 4; j++)
|
||
|
{
|
||
|
r[i*4+j] = a[i*4+0]*b[0*4+j] +
|
||
|
a[i*4+1]*b[1*4+j] +
|
||
|
a[i*4+2]*b[2*4+j] +
|
||
|
a[i*4+3]*b[3*4+j];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
GLAPI GLint APIENTRY
|
||
|
gluProject(GLfloat objx, GLfloat objy, GLfloat objz,
|
||
|
const GLfloat modelMatrix[16],
|
||
|
const GLfloat projMatrix[16],
|
||
|
const GLint viewport[4],
|
||
|
GLfloat* winx, GLfloat* winy, GLfloat* winz)
|
||
|
{
|
||
|
GLfloat in[4];
|
||
|
GLfloat out[4];
|
||
|
|
||
|
in[0]=objx;
|
||
|
in[1]=objy;
|
||
|
in[2]=objz;
|
||
|
in[3]=1.0;
|
||
|
__gluMultMatrixVecf(modelMatrix, in, out);
|
||
|
__gluMultMatrixVecf(projMatrix, out, in);
|
||
|
if (in[3] == 0.0)
|
||
|
{
|
||
|
return(GL_FALSE);
|
||
|
}
|
||
|
|
||
|
in[0]/=in[3];
|
||
|
in[1]/=in[3];
|
||
|
in[2]/=in[3];
|
||
|
/* Map x, y and z to range 0-1 */
|
||
|
in[0]=in[0]*0.5f+0.5f;
|
||
|
in[1]=in[1]*0.5f+0.5f;
|
||
|
in[2]=in[2]*0.5f+0.5f;
|
||
|
|
||
|
/* Map x,y to viewport */
|
||
|
in[0]=in[0] * viewport[2] + viewport[0];
|
||
|
in[1]=in[1] * viewport[3] + viewport[1];
|
||
|
|
||
|
*winx=in[0];
|
||
|
*winy=in[1];
|
||
|
*winz=in[2];
|
||
|
|
||
|
return(GL_TRUE);
|
||
|
}
|
||
|
|
||
|
GLAPI GLint APIENTRY
|
||
|
gluUnProject(GLfloat winx, GLfloat winy, GLfloat winz,
|
||
|
const GLfloat modelMatrix[16],
|
||
|
const GLfloat projMatrix[16],
|
||
|
const GLint viewport[4],
|
||
|
GLfloat* objx, GLfloat* objy, GLfloat* objz)
|
||
|
{
|
||
|
GLfloat finalMatrix[16];
|
||
|
GLfloat in[4];
|
||
|
GLfloat out[4];
|
||
|
|
||
|
__gluMultMatricesf(modelMatrix, projMatrix, finalMatrix);
|
||
|
if (!__gluInvertMatrixf(finalMatrix, finalMatrix))
|
||
|
{
|
||
|
return(GL_FALSE);
|
||
|
}
|
||
|
|
||
|
in[0]=winx;
|
||
|
in[1]=winy;
|
||
|
in[2]=winz;
|
||
|
in[3]=1.0;
|
||
|
|
||
|
/* Map x and y from window coordinates */
|
||
|
in[0] = (in[0] - viewport[0]) / viewport[2];
|
||
|
in[1] = (in[1] - viewport[1]) / viewport[3];
|
||
|
|
||
|
/* Map to range -1 to 1 */
|
||
|
in[0] = in[0] * 2 - 1;
|
||
|
in[1] = in[1] * 2 - 1;
|
||
|
in[2] = in[2] * 2 - 1;
|
||
|
|
||
|
__gluMultMatrixVecf(finalMatrix, in, out);
|
||
|
if (out[3] == 0.0)
|
||
|
{
|
||
|
return(GL_FALSE);
|
||
|
}
|
||
|
|
||
|
out[0] /= out[3];
|
||
|
out[1] /= out[3];
|
||
|
out[2] /= out[3];
|
||
|
*objx = out[0];
|
||
|
*objy = out[1];
|
||
|
*objz = out[2];
|
||
|
|
||
|
return(GL_TRUE);
|
||
|
}
|
||
|
|
||
|
GLAPI GLint APIENTRY
|
||
|
gluUnProject4(GLfloat winx, GLfloat winy, GLfloat winz, GLfloat clipw,
|
||
|
const GLfloat modelMatrix[16],
|
||
|
const GLfloat projMatrix[16],
|
||
|
const GLint viewport[4],
|
||
|
GLclampf nearVal, GLclampf farVal,
|
||
|
GLfloat *objx, GLfloat *objy, GLfloat *objz,
|
||
|
GLfloat *objw)
|
||
|
{
|
||
|
GLfloat finalMatrix[16];
|
||
|
GLfloat in[4];
|
||
|
GLfloat out[4];
|
||
|
|
||
|
__gluMultMatricesf(modelMatrix, projMatrix, finalMatrix);
|
||
|
if (!__gluInvertMatrixf(finalMatrix, finalMatrix))
|
||
|
{
|
||
|
return(GL_FALSE);
|
||
|
}
|
||
|
|
||
|
in[0]=winx;
|
||
|
in[1]=winy;
|
||
|
in[2]=winz;
|
||
|
in[3]=clipw;
|
||
|
|
||
|
/* Map x and y from window coordinates */
|
||
|
in[0] = (in[0] - viewport[0]) / viewport[2];
|
||
|
in[1] = (in[1] - viewport[1]) / viewport[3];
|
||
|
in[2] = (in[2] - nearVal) / (farVal - nearVal);
|
||
|
|
||
|
/* Map to range -1 to 1 */
|
||
|
in[0] = in[0] * 2 - 1;
|
||
|
in[1] = in[1] * 2 - 1;
|
||
|
in[2] = in[2] * 2 - 1;
|
||
|
|
||
|
__gluMultMatrixVecf(finalMatrix, in, out);
|
||
|
if (out[3] == 0.0)
|
||
|
{
|
||
|
return(GL_FALSE);
|
||
|
}
|
||
|
|
||
|
*objx = out[0];
|
||
|
*objy = out[1];
|
||
|
*objz = out[2];
|
||
|
*objw = out[3];
|
||
|
|
||
|
return(GL_TRUE);
|
||
|
}
|
||
|
|
||
|
GLAPI void APIENTRY
|
||
|
gluPickMatrix(GLfloat x, GLfloat y, GLfloat deltax, GLfloat deltay,
|
||
|
GLint viewport[4])
|
||
|
{
|
||
|
if (deltax <= 0 || deltay <= 0)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/* Translate and scale the picked region to the entire window */
|
||
|
glTranslatef((viewport[2] - 2 * (x - viewport[0])) / deltax,
|
||
|
(viewport[3] - 2 * (y - viewport[1])) / deltay, 0);
|
||
|
glScalef(viewport[2] / deltax, viewport[3] / deltay, 1.0);
|
||
|
}
|