hlsdk-xash3d/pm_shared/pm_math.c

419 lines
8.2 KiB
C
Raw Normal View History

2016-06-04 15:24:23 +02:00
/***
*
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
*
* This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved.
*
* Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC.
*
****/
// pm_math.c -- math primitives
2019-10-13 15:37:32 +02:00
#include <math.h>
2016-06-04 15:24:23 +02:00
#include "mathlib.h"
2019-10-13 15:37:32 +02:00
#ifdef HAVE_TGMATH_H
#include <tgmath.h>
#endif
2016-06-04 15:24:23 +02:00
#include "const.h"
// up / down
#define PITCH 0
// left / right
2016-07-31 15:48:50 +02:00
#define YAW 1
2016-06-04 15:24:23 +02:00
// fall over
#define ROLL 2
2017-06-29 15:56:03 +02:00
#ifdef _MSC_VER
2016-06-04 15:24:23 +02:00
#pragma warning(disable : 4244)
2017-06-29 15:56:03 +02:00
#endif
2016-06-04 15:24:23 +02:00
2019-10-13 13:49:25 +02:00
vec3_t vec3_origin = { 0, 0, 0 };
2016-07-31 15:48:50 +02:00
int nanmask = 255 << 23;
2016-06-04 15:24:23 +02:00
2016-07-31 15:48:50 +02:00
float anglemod( float a )
2016-06-04 15:24:23 +02:00
{
2019-10-13 13:49:25 +02:00
a = ( 360.0f / 65536.0f ) * ( (int)( a * ( 65536.0f / 360.0f ) ) & 65535 );
2016-06-04 15:24:23 +02:00
return a;
}
2016-07-31 15:48:50 +02:00
void AngleVectors( const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
float angle;
float sr, sp, sy, cr, cp, cy;
2019-10-13 13:49:25 +02:00
angle = angles[YAW] * ( M_PI_F * 2.0f / 360.0f );
2016-07-31 15:48:50 +02:00
sy = sin( angle );
cy = cos( angle );
2019-10-13 13:49:25 +02:00
angle = angles[PITCH] * ( M_PI_F * 2.0f / 360.0f );
2016-07-31 15:48:50 +02:00
sp = sin( angle );
cp = cos( angle );
2019-10-13 13:49:25 +02:00
angle = angles[ROLL] * ( M_PI_F * 2.0f / 360.0f );
2016-07-31 15:48:50 +02:00
sr = sin( angle );
cr = cos( angle );
if( forward )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
forward[0] = cp * cy;
forward[1] = cp * sy;
2016-06-04 15:24:23 +02:00
forward[2] = -sp;
}
2016-07-31 15:48:50 +02:00
if( right )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
right[0] = ( -1 * sr * sp * cy + -1 * cr * -sy );
right[1] = ( -1 * sr * sp * sy + -1 * cr * cy );
right[2] = -1 * sr * cp;
2016-06-04 15:24:23 +02:00
}
2016-07-31 15:48:50 +02:00
if( up )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
up[0] = ( cr * sp * cy + -sr * -sy );
up[1] = ( cr * sp * sy + -sr * cy );
up[2] = cr * cp;
2016-06-04 15:24:23 +02:00
}
}
2016-07-31 15:48:50 +02:00
void AngleVectorsTranspose( const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
float angle;
float sr, sp, sy, cr, cp, cy;
2016-06-04 15:24:23 +02:00
2019-10-13 13:49:25 +02:00
angle = angles[YAW] * ( M_PI_F * 2.0f / 360.0f );
2016-07-31 15:48:50 +02:00
sy = sin( angle );
cy = cos( angle );
2019-10-13 13:49:25 +02:00
angle = angles[PITCH] * ( M_PI_F * 2.0f / 360.0f );
2016-07-31 15:48:50 +02:00
sp = sin( angle );
cp = cos( angle );
2019-10-13 13:49:25 +02:00
angle = angles[ROLL] * ( M_PI_F * 2.0f / 360.0f );
2016-07-31 15:48:50 +02:00
sr = sin( angle );
cr = cos( angle );
if( forward )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
forward[0] = cp * cy;
forward[1] = ( sr * sp * cy + cr * -sy );
forward[2] = ( cr * sp * cy + -sr * -sy );
2016-06-04 15:24:23 +02:00
}
2016-07-31 15:48:50 +02:00
if( right )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
right[0] = cp * sy;
right[1] = ( sr * sp * sy + cr * cy );
right[2] = ( cr * sp * sy + -sr * cy );
2016-06-04 15:24:23 +02:00
}
2016-07-31 15:48:50 +02:00
if( up )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
up[0] = -sp;
up[1] = sr * cp;
up[2] = cr * cp;
2016-06-04 15:24:23 +02:00
}
}
2016-07-31 15:48:50 +02:00
void AngleMatrix( const vec3_t angles, float (*matrix)[4] )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
float angle;
float sr, sp, sy, cr, cp, cy;
2019-10-13 13:49:25 +02:00
angle = angles[YAW] * ( M_PI_F * 2.0f / 360.0f );
2016-07-31 15:48:50 +02:00
sy = sin( angle );
cy = cos( angle );
2019-10-13 13:49:25 +02:00
angle = angles[PITCH] * ( M_PI_F * 2.0f / 360.0f );
2016-07-31 15:48:50 +02:00
sp = sin( angle );
cp = cos( angle );
2019-10-13 13:49:25 +02:00
angle = angles[ROLL] * ( M_PI_F * 2.0f / 360.0f );
2016-07-31 15:48:50 +02:00
sr = sin( angle );
cr = cos( angle );
// matrix = ( YAW * PITCH ) * ROLL
matrix[0][0] = cp * cy;
matrix[1][0] = cp * sy;
2016-06-04 15:24:23 +02:00
matrix[2][0] = -sp;
2016-07-31 15:48:50 +02:00
matrix[0][1] = sr * sp * cy + cr * -sy;
matrix[1][1] = sr * sp * sy + cr * cy;
matrix[2][1] = sr * cp;
matrix[0][2] = ( cr * sp * cy + -sr * -sy );
matrix[1][2] = ( cr * sp * sy + -sr * cy );
matrix[2][2] = cr * cp;
2019-10-13 13:49:25 +02:00
matrix[0][3] = 0.0f;
matrix[1][3] = 0.0f;
matrix[2][3] = 0.0f;
2016-06-04 15:24:23 +02:00
}
2016-07-31 15:48:50 +02:00
void AngleIMatrix( const vec3_t angles, float matrix[3][4] )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
float angle;
float sr, sp, sy, cr, cp, cy;
2019-10-13 13:49:25 +02:00
angle = angles[YAW] * ( M_PI_F * 2.0f / 360.0f );
2016-07-31 15:48:50 +02:00
sy = sin( angle );
cy = cos( angle );
2019-10-13 13:49:25 +02:00
angle = angles[PITCH] * ( M_PI_F * 2.0f / 360.0f );
2016-07-31 15:48:50 +02:00
sp = sin( angle );
cp = cos( angle );
2019-10-13 13:49:25 +02:00
angle = angles[ROLL] * ( M_PI_F * 2.0f / 360.0f );
2016-07-31 15:48:50 +02:00
sr = sin( angle );
cr = cos( angle );
// matrix = ( YAW * PITCH ) * ROLL
matrix[0][0] = cp * cy;
matrix[0][1] = cp * sy;
2016-06-04 15:24:23 +02:00
matrix[0][2] = -sp;
2016-07-31 15:48:50 +02:00
matrix[1][0] = sr * sp * cy + cr * -sy;
matrix[1][1] = sr * sp * sy + cr * cy;
matrix[1][2] = sr * cp;
matrix[2][0] = ( cr * sp * cy + -sr * -sy );
matrix[2][1] = ( cr * sp * sy + -sr * cy );
matrix[2][2] = cr * cp;
2016-06-04 15:24:23 +02:00
matrix[0][3] = 0.0;
matrix[1][3] = 0.0;
matrix[2][3] = 0.0;
}
void NormalizeAngles( float *angles )
{
int i;
// Normalize angles
2016-07-31 15:48:50 +02:00
for( i = 0; i < 3; i++ )
2016-06-04 15:24:23 +02:00
{
2019-10-13 13:49:25 +02:00
if( angles[i] > 180.0f )
2016-06-04 15:24:23 +02:00
{
2019-10-13 13:49:25 +02:00
angles[i] -= 360.0f;
2016-06-04 15:24:23 +02:00
}
2019-10-13 13:49:25 +02:00
else if( angles[i] < -180.0f )
2016-06-04 15:24:23 +02:00
{
2019-10-13 13:49:25 +02:00
angles[i] += 360.0f;
2016-06-04 15:24:23 +02:00
}
}
}
/*
===================
InterpolateAngles
Interpolate Euler angles.
FIXME: Use Quaternions to avoid discontinuities
Frac is 0.0 to 1.0 ( i.e., should probably be clamped, but doesn't have to be )
===================
*/
void InterpolateAngles( float *start, float *end, float *output, float frac )
{
int i;
float ang1, ang2;
float d;
2016-07-31 15:48:50 +02:00
2016-06-04 15:24:23 +02:00
NormalizeAngles( start );
NormalizeAngles( end );
2016-07-31 15:48:50 +02:00
for( i = 0; i < 3; i++ )
2016-06-04 15:24:23 +02:00
{
ang1 = start[i];
ang2 = end[i];
d = ang2 - ang1;
2019-10-13 13:49:25 +02:00
if( d > 180.0f )
2016-06-04 15:24:23 +02:00
{
2019-10-13 13:49:25 +02:00
d -= 360.0f;
2016-06-04 15:24:23 +02:00
}
2019-10-13 13:49:25 +02:00
else if( d < -180.0f )
2016-06-04 15:24:23 +02:00
{
2019-10-13 13:49:25 +02:00
d += 360.0f;
2016-06-04 15:24:23 +02:00
}
output[i] = ang1 + d * frac;
}
NormalizeAngles( output );
}
/*
===================
AngleBetweenVectors
===================
*/
float AngleBetweenVectors( const vec3_t v1, const vec3_t v2 )
{
float angle;
float l1 = Length( v1 );
float l2 = Length( v2 );
2016-07-31 15:48:50 +02:00
if( !l1 || !l2 )
2016-06-04 15:24:23 +02:00
return 0.0f;
angle = acos( DotProduct( v1, v2 ) / ( l1 * l2 ) );
2019-10-13 13:49:25 +02:00
angle = ( angle * 180.0f ) / M_PI_F;
2016-06-04 15:24:23 +02:00
return angle;
}
2016-07-31 15:48:50 +02:00
void VectorTransform( const vec3_t in1, float in2[3][4], vec3_t out )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
out[0] = DotProduct( in1, in2[0] ) + in2[0][3];
out[1] = DotProduct( in1, in2[1] ) + in2[1][3];
out[2] = DotProduct( in1, in2[2] ) + in2[2][3];
2016-06-04 15:24:23 +02:00
}
2016-07-31 15:48:50 +02:00
int VectorCompare( const vec3_t v1, const vec3_t v2 )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
int i;
for( i = 0; i < 3; i++ )
if( v1[i] != v2[i] )
2016-06-04 15:24:23 +02:00
return 0;
2016-07-31 15:48:50 +02:00
2016-06-04 15:24:23 +02:00
return 1;
}
2016-07-31 15:48:50 +02:00
void VectorMA( const vec3_t veca, float scale, const vec3_t vecb, vec3_t vecc )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
vecc[0] = veca[0] + scale * vecb[0];
vecc[1] = veca[1] + scale * vecb[1];
vecc[2] = veca[2] + scale * vecb[2];
2016-06-04 15:24:23 +02:00
}
2016-07-31 15:48:50 +02:00
vec_t _DotProduct( vec3_t v1, vec3_t v2 )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
2016-06-04 15:24:23 +02:00
}
2016-07-31 15:48:50 +02:00
void _VectorSubtract( vec3_t veca, vec3_t vecb, vec3_t out )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
out[0] = veca[0] - vecb[0];
out[1] = veca[1] - vecb[1];
out[2] = veca[2] - vecb[2];
2016-06-04 15:24:23 +02:00
}
2016-07-31 15:48:50 +02:00
void _VectorAdd( vec3_t veca, vec3_t vecb, vec3_t out )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
out[0] = veca[0] + vecb[0];
out[1] = veca[1] + vecb[1];
out[2] = veca[2] + vecb[2];
2016-06-04 15:24:23 +02:00
}
2016-07-31 15:48:50 +02:00
void _VectorCopy( vec3_t in, vec3_t out )
2016-06-04 15:24:23 +02:00
{
out[0] = in[0];
out[1] = in[1];
out[2] = in[2];
}
2016-07-31 15:48:50 +02:00
void CrossProduct( const vec3_t v1, const vec3_t v2, vec3_t cross )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
cross[0] = v1[1] * v2[2] - v1[2] * v2[1];
cross[1] = v1[2] * v2[0] - v1[0] * v2[2];
cross[2] = v1[0] * v2[1] - v1[1] * v2[0];
2016-06-04 15:24:23 +02:00
}
2016-07-31 15:48:50 +02:00
double sqrt( double x );
2016-06-04 15:24:23 +02:00
2016-07-31 15:48:50 +02:00
float Length( const vec3_t v )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
int i;
float length = 0.0f;
for( i = 0; i < 3; i++ )
length += v[i] * v[i];
length = sqrt( length ); // FIXME
2016-06-04 15:24:23 +02:00
return length;
}
2016-07-31 15:48:50 +02:00
float Distance( const vec3_t v1, const vec3_t v2 )
2016-06-04 15:24:23 +02:00
{
vec3_t d;
2016-07-31 15:48:50 +02:00
VectorSubtract( v2, v1, d );
return Length( d );
2016-06-04 15:24:23 +02:00
}
2016-07-31 15:48:50 +02:00
float VectorNormalize( vec3_t v )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
float length, ilength;
2016-06-04 15:24:23 +02:00
2016-07-31 15:48:50 +02:00
length = v[0] * v[0] + v[1] * v[1] + v[2] * v[2];
length = sqrt( length ); // FIXME
2016-06-04 15:24:23 +02:00
2016-07-31 15:48:50 +02:00
if( length )
2016-06-04 15:24:23 +02:00
{
2019-10-13 13:49:25 +02:00
ilength = 1.0f / length;
2016-06-04 15:24:23 +02:00
v[0] *= ilength;
v[1] *= ilength;
v[2] *= ilength;
}
2016-07-31 15:48:50 +02:00
return length;
2016-06-04 15:24:23 +02:00
}
2016-07-31 15:48:50 +02:00
void VectorInverse( vec3_t v )
2016-06-04 15:24:23 +02:00
{
v[0] = -v[0];
v[1] = -v[1];
v[2] = -v[2];
}
2016-07-31 15:48:50 +02:00
void VectorScale( const vec3_t in, vec_t scale, vec3_t out )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
out[0] = in[0] * scale;
out[1] = in[1] * scale;
out[2] = in[2] * scale;
2016-06-04 15:24:23 +02:00
}
2016-07-31 15:48:50 +02:00
int Q_log2( int val )
2016-06-04 15:24:23 +02:00
{
2016-07-31 15:48:50 +02:00
int answer = 0;
while( val >>= 1 )
2016-06-04 15:24:23 +02:00
answer++;
return answer;
}
2016-07-31 15:48:50 +02:00
void VectorMatrix( vec3_t forward, vec3_t right, vec3_t up )
2016-06-04 15:24:23 +02:00
{
vec3_t tmp;
2019-10-13 13:49:25 +02:00
if( forward[0] == 0.0f && forward[1] == 0.0f )
2016-06-04 15:24:23 +02:00
{
2019-10-13 13:49:25 +02:00
right[0] = 1.0f;
right[1] = 0.0f;
right[2] = 0.0f;
2016-06-04 15:24:23 +02:00
up[0] = -forward[2];
2019-10-13 13:49:25 +02:00
up[1] = 0.0f;
up[2] = 0.0f;
2016-06-04 15:24:23 +02:00
return;
}
2019-10-13 13:49:25 +02:00
tmp[0] = 0.0f; tmp[1] = 0.0f; tmp[2] = 1.0f;
2016-06-04 15:24:23 +02:00
CrossProduct( forward, tmp, right );
VectorNormalize( right );
CrossProduct( right, forward, up );
VectorNormalize( up );
}
void VectorAngles( const vec3_t forward, vec3_t angles )
{
2016-07-31 15:48:50 +02:00
float tmp, yaw, pitch;
2019-10-13 13:49:25 +02:00
if( forward[1] == 0.0f && forward[0] == 0.0f )
2016-06-04 15:24:23 +02:00
{
2019-10-13 13:49:25 +02:00
yaw = 0.0f;
if( forward[2] > 0.0f )
pitch = 90.0f;
2016-06-04 15:24:23 +02:00
else
2019-10-13 13:49:25 +02:00
pitch = 270.0f;
2016-06-04 15:24:23 +02:00
}
else
{
2019-10-13 13:49:25 +02:00
yaw = ( atan2( forward[1], forward[0] ) * 180.0f / M_PI_F );
if( yaw < 0.0f )
yaw += 360.0f;
2016-06-04 15:24:23 +02:00
2016-07-31 15:48:50 +02:00
tmp = sqrt( forward[0] * forward[0] + forward[1] * forward[1] );
2019-10-13 13:49:25 +02:00
pitch = ( atan2( forward[2], tmp ) * 180.0f / M_PI_F );
if( pitch < 0.0f )
pitch += 360.0f;
2016-06-04 15:24:23 +02:00
}
2016-07-31 15:48:50 +02:00
2016-06-04 15:24:23 +02:00
angles[0] = pitch;
angles[1] = yaw;
2019-10-13 13:49:25 +02:00
angles[2] = 0.0f;
2016-06-04 15:24:23 +02:00
}