343 lines
8.8 KiB
C
343 lines
8.8 KiB
C
/*
|
|
Copyright (C) 2002-2007 Victor Luchits
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; either version 2
|
|
of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
See the GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
// r_math.c
|
|
|
|
#include "r_local.h"
|
|
#include "r_math.h"
|
|
#include "mathlib.h"
|
|
|
|
const mat4x4_t mat4x4_identity =
|
|
{
|
|
1, 0, 0, 0,
|
|
0, 1, 0, 0,
|
|
0, 0, 1, 0,
|
|
0, 0, 0, 1
|
|
};
|
|
|
|
void Matrix4_Identity( mat4x4_t m )
|
|
{
|
|
int i;
|
|
|
|
for( i = 0; i < 16; i++ )
|
|
{
|
|
if( i == 0 || i == 5 || i == 10 || i == 15 )
|
|
m[i] = 1.0;
|
|
else
|
|
m[i] = 0.0;
|
|
}
|
|
}
|
|
|
|
void Matrix4_Copy( const mat4x4_t m1, mat4x4_t m2 )
|
|
{
|
|
int i;
|
|
|
|
for( i = 0; i < 16; i++ )
|
|
m2[i] = m1[i];
|
|
}
|
|
|
|
bool Matrix4_Compare( const mat4x4_t m1, const mat4x4_t m2 )
|
|
{
|
|
int i;
|
|
|
|
for( i = 0; i < 16; i++ )
|
|
if( m1[i] != m2[i] )
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
void Matrix4_Multiply( const mat4x4_t m1, const mat4x4_t m2, mat4x4_t out )
|
|
{
|
|
out[0] = m1[0] * m2[0] + m1[4] * m2[1] + m1[8] * m2[2] + m1[12] * m2[3];
|
|
out[1] = m1[1] * m2[0] + m1[5] * m2[1] + m1[9] * m2[2] + m1[13] * m2[3];
|
|
out[2] = m1[2] * m2[0] + m1[6] * m2[1] + m1[10] * m2[2] + m1[14] * m2[3];
|
|
out[3] = m1[3] * m2[0] + m1[7] * m2[1] + m1[11] * m2[2] + m1[15] * m2[3];
|
|
out[4] = m1[0] * m2[4] + m1[4] * m2[5] + m1[8] * m2[6] + m1[12] * m2[7];
|
|
out[5] = m1[1] * m2[4] + m1[5] * m2[5] + m1[9] * m2[6] + m1[13] * m2[7];
|
|
out[6] = m1[2] * m2[4] + m1[6] * m2[5] + m1[10] * m2[6] + m1[14] * m2[7];
|
|
out[7] = m1[3] * m2[4] + m1[7] * m2[5] + m1[11] * m2[6] + m1[15] * m2[7];
|
|
out[8] = m1[0] * m2[8] + m1[4] * m2[9] + m1[8] * m2[10] + m1[12] * m2[11];
|
|
out[9] = m1[1] * m2[8] + m1[5] * m2[9] + m1[9] * m2[10] + m1[13] * m2[11];
|
|
out[10] = m1[2] * m2[8] + m1[6] * m2[9] + m1[10] * m2[10] + m1[14] * m2[11];
|
|
out[11] = m1[3] * m2[8] + m1[7] * m2[9] + m1[11] * m2[10] + m1[15] * m2[11];
|
|
out[12] = m1[0] * m2[12] + m1[4] * m2[13] + m1[8] * m2[14] + m1[12] * m2[15];
|
|
out[13] = m1[1] * m2[12] + m1[5] * m2[13] + m1[9] * m2[14] + m1[13] * m2[15];
|
|
out[14] = m1[2] * m2[12] + m1[6] * m2[13] + m1[10] * m2[14] + m1[14] * m2[15];
|
|
out[15] = m1[3] * m2[12] + m1[7] * m2[13] + m1[11] * m2[14] + m1[15] * m2[15];
|
|
}
|
|
|
|
void Matrix4_MultiplyFast( const mat4x4_t m1, const mat4x4_t m2, mat4x4_t out )
|
|
{
|
|
out[0] = m1[0] * m2[0] + m1[4] * m2[1] + m1[8] * m2[2];
|
|
out[1] = m1[1] * m2[0] + m1[5] * m2[1] + m1[9] * m2[2];
|
|
out[2] = m1[2] * m2[0] + m1[6] * m2[1] + m1[10] * m2[2];
|
|
out[3] = 0.0f;
|
|
out[4] = m1[0] * m2[4] + m1[4] * m2[5] + m1[8] * m2[6];
|
|
out[5] = m1[1] * m2[4] + m1[5] * m2[5] + m1[9] * m2[6];
|
|
out[6] = m1[2] * m2[4] + m1[6] * m2[5] + m1[10] * m2[6];
|
|
out[7] = 0.0f;
|
|
out[8] = m1[0] * m2[8] + m1[4] * m2[9] + m1[8] * m2[10];
|
|
out[9] = m1[1] * m2[8] + m1[5] * m2[9] + m1[9] * m2[10];
|
|
out[10] = m1[2] * m2[8] + m1[6] * m2[9] + m1[10] * m2[10];
|
|
out[11] = 0.0f;
|
|
out[12] = m1[0] * m2[12] + m1[4] * m2[13] + m1[8] * m2[14] + m1[12];
|
|
out[13] = m1[1] * m2[12] + m1[5] * m2[13] + m1[9] * m2[14] + m1[13];
|
|
out[14] = m1[2] * m2[12] + m1[6] * m2[13] + m1[10] * m2[14] + m1[14];
|
|
out[15] = 1.0f;
|
|
}
|
|
|
|
void Matrix_FromQuaternion( const quat_t q, mat4x4_t out )
|
|
{
|
|
vec_t wx, wy, wz, xx, yy, yz, xy, xz, zz, x2, y2, z2;
|
|
|
|
x2 = q[0] + q[0]; y2 = q[1] + q[1]; z2 = q[2] + q[2];
|
|
|
|
xx = q[0] * x2; yy = q[1] * y2; zz = q[2] * z2;
|
|
out[0] = 1.0f - yy - zz; out[5] = 1.0f - xx - zz; out[10] = 1.0f - xx - yy;
|
|
|
|
yz = q[1] * z2; wx = q[3] * x2;
|
|
out[9] = yz - wx; out[6] = yz + wx;
|
|
|
|
xy = q[0] * y2; wz = q[3] * z2;
|
|
out[4] = xy - wz; out[1] = xy + wz;
|
|
|
|
xz = q[0] * z2; wy = q[3] * y2;
|
|
out[8] = xz + wy; out[2] = xz - wy;
|
|
}
|
|
|
|
void Matrix4_Rotate( mat4x4_t m, vec_t angle, vec_t x, vec_t y, vec_t z )
|
|
{
|
|
mat4x4_t t, b;
|
|
vec_t c = cos( DEG2RAD( angle ) );
|
|
vec_t s = sin( DEG2RAD( angle ) );
|
|
vec_t mc = 1 - c, t1, t2;
|
|
|
|
t[0] = ( x * x * mc ) + c;
|
|
t[5] = ( y * y * mc ) + c;
|
|
t[10] = ( z * z * mc ) + c;
|
|
|
|
t1 = y * x * mc;
|
|
t2 = z * s;
|
|
t[1] = t1 + t2;
|
|
t[4] = t1 - t2;
|
|
|
|
t1 = x * z * mc;
|
|
t2 = y * s;
|
|
t[2] = t1 - t2;
|
|
t[8] = t1 + t2;
|
|
|
|
t1 = y * z * mc;
|
|
t2 = x * s;
|
|
t[6] = t1 + t2;
|
|
t[9] = t1 - t2;
|
|
|
|
t[3] = t[7] = t[11] = t[12] = t[13] = t[14] = 0;
|
|
t[15] = 1;
|
|
|
|
Matrix4_Copy( m, b );
|
|
Matrix4_MultiplyFast( b, t, m );
|
|
}
|
|
|
|
void Matrix4_Translate( mat4x4_t m, vec_t x, vec_t y, vec_t z )
|
|
{
|
|
m[12] = m[0] * x + m[4] * y + m[8] * z + m[12];
|
|
m[13] = m[1] * x + m[5] * y + m[9] * z + m[13];
|
|
m[14] = m[2] * x + m[6] * y + m[10] * z + m[14];
|
|
m[15] = m[3] * x + m[7] * y + m[11] * z + m[15];
|
|
}
|
|
|
|
void Matrix4_Scale( mat4x4_t m, vec_t x, vec_t y, vec_t z )
|
|
{
|
|
m[0] *= x; m[4] *= y; m[8] *= z;
|
|
m[1] *= x; m[5] *= y; m[9] *= z;
|
|
m[2] *= x; m[6] *= y; m[10] *= z;
|
|
m[3] *= x; m[7] *= y; m[11] *= z;
|
|
}
|
|
|
|
void Matrix4_Transpose( const mat4x4_t m, mat4x4_t out )
|
|
{
|
|
out[0] = m[0]; out[1] = m[4]; out[2] = m[8]; out[3] = m[12];
|
|
out[4] = m[1]; out[5] = m[5]; out[6] = m[9]; out[7] = m[13];
|
|
out[8] = m[2]; out[9] = m[6]; out[10] = m[10]; out[11] = m[14];
|
|
out[12] = m[3]; out[13] = m[7]; out[14] = m[11]; out[15] = m[15];
|
|
}
|
|
|
|
void Matrix4_Matrix( const mat4x4_t in, vec3_t out[3] )
|
|
{
|
|
out[0][0] = in[0];
|
|
out[0][1] = in[4];
|
|
out[0][2] = in[8];
|
|
|
|
out[1][0] = in[1];
|
|
out[1][1] = in[5];
|
|
out[1][2] = in[9];
|
|
|
|
out[2][0] = in[2];
|
|
out[2][1] = in[6];
|
|
out[2][2] = in[10];
|
|
}
|
|
|
|
void Matrix4_Multiply_Vector( const mat4x4_t m, const vec4_t v, vec4_t out )
|
|
{
|
|
out[0] = m[0] * v[0] + m[4] * v[1] + m[8] * v[2] + m[12] * v[3];
|
|
out[1] = m[1] * v[0] + m[5] * v[1] + m[9] * v[2] + m[13] * v[3];
|
|
out[2] = m[2] * v[0] + m[6] * v[1] + m[10] * v[2] + m[14] * v[3];
|
|
out[3] = m[3] * v[0] + m[7] * v[1] + m[11] * v[2] + m[15] * v[3];
|
|
}
|
|
|
|
//============================================================================
|
|
|
|
void Matrix4_Copy2D( const mat4x4_t m1, mat4x4_t m2 )
|
|
{
|
|
m2[0] = m1[0];
|
|
m2[1] = m1[1];
|
|
m2[4] = m1[4];
|
|
m2[5] = m1[5];
|
|
m2[12] = m1[12];
|
|
m2[13] = m1[13];
|
|
}
|
|
|
|
void Matrix4_Multiply2D( const mat4x4_t m1, const mat4x4_t m2, mat4x4_t out )
|
|
{
|
|
out[0] = m1[0] * m2[0] + m1[4] * m2[1];
|
|
out[1] = m1[1] * m2[0] + m1[5] * m2[1];
|
|
out[4] = m1[0] * m2[4] + m1[4] * m2[5];
|
|
out[5] = m1[1] * m2[4] + m1[5] * m2[5];
|
|
out[12] = m1[0] * m2[12] + m1[4] * m2[13] + m1[12];
|
|
out[13] = m1[1] * m2[12] + m1[5] * m2[13] + m1[13];
|
|
}
|
|
|
|
void Matrix4_Scale2D( mat4x4_t m, vec_t x, vec_t y )
|
|
{
|
|
m[0] *= x;
|
|
m[1] *= x;
|
|
m[4] *= y;
|
|
m[5] *= y;
|
|
}
|
|
|
|
void Matrix4_Translate2D( mat4x4_t m, vec_t x, vec_t y )
|
|
{
|
|
m[12] += x;
|
|
m[13] += y;
|
|
}
|
|
|
|
void Matrix4_Stretch2D( mat4x4_t m, vec_t s, vec_t t )
|
|
{
|
|
m[0] *= s;
|
|
m[1] *= s;
|
|
m[4] *= s;
|
|
m[5] *= s;
|
|
m[12] = s * m[12] + t;
|
|
m[13] = s * m[13] + t;
|
|
}
|
|
|
|
/*
|
|
====================
|
|
CalcFov
|
|
====================
|
|
*/
|
|
float CalcFov( float fov_x, float width, float height )
|
|
{
|
|
float x;
|
|
|
|
if( fov_x < 1 || fov_x > 179 )
|
|
Host_Error( "bad fov: %f\n", fov_x );
|
|
|
|
x = width / tan( fov_x / 360 * M_PI );
|
|
|
|
return atan( height / x ) * 360 / M_PI;
|
|
}
|
|
|
|
/*
|
|
====================
|
|
AdjustFov
|
|
====================
|
|
*/
|
|
void AdjustFov( float *fov_x, float *fov_y, float width, float height, bool lock_x )
|
|
{
|
|
float x, y;
|
|
|
|
if( width * 3 == 4 * height || width * 4 == height * 5 )
|
|
{
|
|
// 4:3 or 5:4 ratio
|
|
return;
|
|
}
|
|
|
|
if( lock_x )
|
|
{
|
|
*fov_y = 2 * atan((width * 3) / (height * 4) * tan (*fov_y * M_PI / 360.0 * 0.5) ) * 360 / M_PI;
|
|
return;
|
|
}
|
|
|
|
y = CalcFov( *fov_x, 640, 480 );
|
|
x = *fov_x;
|
|
|
|
*fov_x = CalcFov( y, height, width );
|
|
if( *fov_x < x ) *fov_x = x;
|
|
else *fov_y = y;
|
|
}
|
|
|
|
/*
|
|
=================
|
|
SignbitsForPlane
|
|
|
|
fast box on planeside test
|
|
=================
|
|
*/
|
|
int SignbitsForPlane( const cplane_t *out )
|
|
{
|
|
int bits, i;
|
|
|
|
for( i = bits = 0; i < 3; i++ )
|
|
if( out->normal[i] < 0.0f ) bits |= 1<<i;
|
|
return bits;
|
|
}
|
|
|
|
/*
|
|
=================
|
|
PlaneTypeForNormal
|
|
=================
|
|
*/
|
|
int PlaneTypeForNormal( const vec3_t normal )
|
|
{
|
|
// NOTE: should these have an epsilon around 1.0?
|
|
if( normal[0] >= 1.0f ) return PLANE_X;
|
|
if( normal[1] >= 1.0f ) return PLANE_Y;
|
|
if( normal[2] >= 1.0f ) return PLANE_Z;
|
|
return PLANE_NONAXIAL;
|
|
}
|
|
|
|
|
|
/*
|
|
=================
|
|
PlaneFromPoints
|
|
=================
|
|
*/
|
|
void PlaneFromPoints( vec3_t verts[3], cplane_t *plane )
|
|
{
|
|
vec3_t v1, v2;
|
|
|
|
VectorSubtract( verts[1], verts[0], v1 );
|
|
VectorSubtract( verts[2], verts[0], v2 );
|
|
CrossProduct( v2, v1, plane->normal );
|
|
VectorNormalize( plane->normal );
|
|
plane->dist = DotProduct( verts[0], plane->normal );
|
|
} |