1225 lines
30 KiB
C
1225 lines
30 KiB
C
/*
|
|
Copyright (C) 1996-1997 Id Software, Inc.
|
|
|
|
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.
|
|
|
|
*/
|
|
// mathlib.c -- math primitives
|
|
|
|
//Dan East:
|
|
//I've made many additions to this file, recreating various original functions to use
|
|
//my Fixed Point Math routines. My additions all contain the acronym FPM
|
|
|
|
#include <math.h>
|
|
#include "quakedef.h"
|
|
|
|
void Sys_Error (char *error, ...);
|
|
|
|
vec3_t vec3_origin = {0,0,0};
|
|
#ifdef USEFPM
|
|
vec3_FPM_t vec3_originFPM = {0,0,0};
|
|
#endif
|
|
int nanmask = 255<<23;
|
|
|
|
/*-----------------------------------------------------------------*/
|
|
|
|
#define DEG2RAD( a ) ( a * M_PI ) / 180.0F
|
|
|
|
void ProjectPointOnPlane( vec3_t dst, const vec3_t p, const vec3_t normal )
|
|
{
|
|
float d;
|
|
vec3_t n;
|
|
float inv_denom;
|
|
|
|
inv_denom = 1.0F / DotProduct( normal, normal );
|
|
|
|
d = DotProduct( normal, p ) * inv_denom;
|
|
|
|
n[0] = normal[0] * inv_denom;
|
|
n[1] = normal[1] * inv_denom;
|
|
n[2] = normal[2] * inv_denom;
|
|
|
|
dst[0] = p[0] - d * n[0];
|
|
dst[1] = p[1] - d * n[1];
|
|
dst[2] = p[2] - d * n[2];
|
|
}
|
|
|
|
#ifdef USEFPM
|
|
void ProjectPointOnPlaneFPM( vec3_FPM_t dst, const vec3_FPM_t p, const vec3_FPM_t normal )
|
|
{
|
|
fixedpoint_t d;
|
|
vec3_FPM_t n;
|
|
fixedpoint_t inv_denom;
|
|
|
|
inv_denom = /*1.0F*/0x10000 / DotProductFPM( normal, normal );
|
|
|
|
d = DotProductFPM( normal, p ) * inv_denom;
|
|
|
|
n[0] = FPM_MUL(normal[0], inv_denom);
|
|
n[1] = FPM_MUL(normal[1], inv_denom);
|
|
n[2] = FPM_MUL(normal[2], inv_denom);
|
|
|
|
dst[0] = FPM_SUB(p[0], FPM_MUL(d, n[0]));
|
|
dst[1] = FPM_SUB(p[1], FPM_MUL(d, n[1]));
|
|
dst[2] = FPM_SUB(p[2], FPM_MUL(d, n[2]));
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
** assumes "src" is normalized
|
|
*/
|
|
void PerpendicularVector( vec3_t dst, const vec3_t src )
|
|
{
|
|
int pos;
|
|
int i;
|
|
float minelem = 1.0F;
|
|
vec3_t tempvec;
|
|
|
|
/*
|
|
** find the smallest magnitude axially aligned vector
|
|
*/
|
|
for ( pos = 0, i = 0; i < 3; i++ )
|
|
{
|
|
if ( fabs( src[i] ) < minelem )
|
|
{
|
|
pos = i;
|
|
minelem = (float)fabs( src[i] );
|
|
}
|
|
}
|
|
tempvec[0] = tempvec[1] = tempvec[2] = 0.0F;
|
|
tempvec[pos] = 1.0F;
|
|
|
|
/*
|
|
** project the point onto the plane defined by src
|
|
*/
|
|
ProjectPointOnPlane( dst, tempvec, src );
|
|
|
|
/*
|
|
** normalize the result
|
|
*/
|
|
VectorNormalize( dst );
|
|
}
|
|
|
|
#ifdef USEFPM
|
|
void PerpendicularVectorFPM( vec3_FPM_t dst, const vec3_FPM_t src )
|
|
{
|
|
int pos;
|
|
int i;
|
|
fixedpoint_t minelem = 0x00010000;
|
|
vec3_FPM_t tempvec;
|
|
|
|
/*
|
|
** find the smallest magnitude axially aligned vector
|
|
*/
|
|
for ( pos = 0, i = 0; i < 3; i++ )
|
|
{
|
|
if ( FPM_ABS( src[i] ) < minelem )
|
|
{
|
|
pos = i;
|
|
minelem = FPM_ABS( src[i] );
|
|
}
|
|
}
|
|
tempvec[0] = tempvec[1] = tempvec[2] = 0;
|
|
tempvec[pos] = 0x10000;
|
|
|
|
/*
|
|
** project the point onto the plane defined by src
|
|
*/
|
|
ProjectPointOnPlaneFPM( dst, tempvec, src );
|
|
|
|
/*
|
|
** normalize the result
|
|
*/
|
|
VectorNormalizeFPM( dst );
|
|
}
|
|
#endif
|
|
|
|
#ifdef _WIN32
|
|
#pragma optimize( "", off )
|
|
#endif
|
|
|
|
|
|
void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees )
|
|
{
|
|
float m[3][3];
|
|
float im[3][3];
|
|
float zrot[3][3];
|
|
float tmpmat[3][3];
|
|
float rot[3][3];
|
|
int i;
|
|
vec3_t vr, vup, vf;
|
|
|
|
vf[0] = dir[0];
|
|
vf[1] = dir[1];
|
|
vf[2] = dir[2];
|
|
|
|
PerpendicularVector( vr, dir );
|
|
CrossProduct( vr, vf, vup );
|
|
|
|
m[0][0] = vr[0];
|
|
m[1][0] = vr[1];
|
|
m[2][0] = vr[2];
|
|
|
|
m[0][1] = vup[0];
|
|
m[1][1] = vup[1];
|
|
m[2][1] = vup[2];
|
|
|
|
m[0][2] = vf[0];
|
|
m[1][2] = vf[1];
|
|
m[2][2] = vf[2];
|
|
|
|
Q_memcpy( im, m, sizeof( im ) );
|
|
|
|
im[0][1] = m[1][0];
|
|
im[0][2] = m[2][0];
|
|
im[1][0] = m[0][1];
|
|
im[1][2] = m[2][1];
|
|
im[2][0] = m[0][2];
|
|
im[2][1] = m[1][2];
|
|
|
|
Q_memset( zrot, 0, sizeof( zrot ) );
|
|
zrot[0][0] = zrot[1][1] = zrot[2][2] = 1.0F;
|
|
|
|
zrot[0][0] = (float)cos( DEG2RAD( degrees ) );
|
|
zrot[0][1] = (float)sin( DEG2RAD( degrees ) );
|
|
zrot[1][0] = (float)-sin( DEG2RAD( degrees ) );
|
|
zrot[1][1] = (float)cos( DEG2RAD( degrees ) );
|
|
|
|
R_ConcatRotations( m, zrot, tmpmat );
|
|
R_ConcatRotations( tmpmat, im, rot );
|
|
|
|
for ( i = 0; i < 3; i++ )
|
|
{
|
|
dst[i] = rot[i][0] * point[0] + rot[i][1] * point[1] + rot[i][2] * point[2];
|
|
}
|
|
}
|
|
|
|
#ifdef USEFPM
|
|
void RotatePointAroundVectorFPM( vec3_FPM_t dst, const vec3_FPM_t dir, const vec3_FPM_t point, fixedpoint_t degrees )
|
|
{
|
|
fixedpoint_t m[3][3];
|
|
fixedpoint_t im[3][3];
|
|
fixedpoint_t zrot[3][3];
|
|
fixedpoint_t tmpmat[3][3];
|
|
fixedpoint_t rot[3][3];
|
|
int i;
|
|
vec3_FPM_t vr, vup, vf;
|
|
|
|
vf[0] = dir[0];
|
|
vf[1] = dir[1];
|
|
vf[2] = dir[2];
|
|
|
|
PerpendicularVectorFPM( vr, dir );
|
|
CrossProductFPM( vr, vf, vup );
|
|
|
|
m[0][0] = vr[0];
|
|
m[1][0] = vr[1];
|
|
m[2][0] = vr[2];
|
|
|
|
m[0][1] = vup[0];
|
|
m[1][1] = vup[1];
|
|
m[2][1] = vup[2];
|
|
|
|
m[0][2] = vf[0];
|
|
m[1][2] = vf[1];
|
|
m[2][2] = vf[2];
|
|
|
|
Q_memcpy( im, m, sizeof( im ) );
|
|
|
|
im[0][1] = m[1][0];
|
|
im[0][2] = m[2][0];
|
|
im[1][0] = m[0][1];
|
|
im[1][2] = m[2][1];
|
|
im[2][0] = m[0][2];
|
|
im[2][1] = m[1][2];
|
|
|
|
Q_memset( zrot, 0, sizeof( zrot ) );
|
|
zrot[0][0] = zrot[1][1] = zrot[2][2] = 0x10000;
|
|
|
|
zrot[1][0]=-(zrot[0][0] = FPM_SIN_DEG(degrees));
|
|
zrot[1][1] = FPM_COS_DEG( degrees );
|
|
|
|
R_ConcatRotationsFPM( m, zrot, tmpmat );
|
|
R_ConcatRotationsFPM( tmpmat, im, rot );
|
|
|
|
for ( i = 0; i < 3; i++ )
|
|
{
|
|
dst[i] = FPM_ADD3(FPM_MUL(rot[i][0], point[0]), FPM_MUL(rot[i][1], point[1]), FPM_MUL(rot[i][2], point[2]));
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifdef _WIN32
|
|
#pragma optimize( "", on )
|
|
#endif
|
|
|
|
/*-----------------------------------------------------------------*/
|
|
|
|
|
|
float anglemod(float a)
|
|
{
|
|
#if 0
|
|
if (a >= 0)
|
|
a -= 360*(int)(a/360);
|
|
else
|
|
a += 360*( 1 + (int)(-a/360) );
|
|
#endif
|
|
a = (float)((360.0/65536) * ((int)(a*(65536/360.0)) & 65535));
|
|
return a;
|
|
}
|
|
|
|
#ifdef USEFPM
|
|
fixedpoint_t anglemodFPM(fixedpoint_t a)
|
|
{
|
|
#if 0
|
|
if (a >= 0)
|
|
a -= 360*(int)(a/360);
|
|
else
|
|
a += 360*( 1 + (int)(-a/360) );
|
|
#endif
|
|
//Dan: TODO: the following will overflow 16.16 signed fixedpoint. This algorithm
|
|
//needs to be tweaked to work with fixedpoint without overflowing.
|
|
a = FPM_FROMFLOAT((float)((360.0/65536) * ((int)(FPM_TOFLOAT(a)*(65536/360.0)) & 65535)));
|
|
|
|
// a = FPM_MUL(FPM_FROMFLOAT(360.0/65536), FPM_FROMLONG((FPM_TOLONG(FPM_MUL(a,FPM_FROMFLOAT(65536/360.0))) & 65535)));
|
|
return a;
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
==================
|
|
BOPS_Error
|
|
|
|
Split out like this for ASM to call.
|
|
==================
|
|
*/
|
|
void BOPS_Error (void)
|
|
{
|
|
Sys_Error ("BoxOnPlaneSide: Bad signbits");
|
|
}
|
|
|
|
|
|
#if !id386
|
|
|
|
/*
|
|
==================
|
|
BoxOnPlaneSide
|
|
|
|
Returns 1, 2, or 1 + 2
|
|
==================
|
|
*/
|
|
int BoxOnPlaneSide (vec3_t emins, vec3_t emaxs, mplane_t *p)
|
|
{
|
|
float dist1, dist2;
|
|
int sides;
|
|
|
|
#if 0 // this is done by the BOX_ON_PLANE_SIDE macro before calling this
|
|
// function
|
|
// fast axial cases
|
|
if (p->type < 3)
|
|
{
|
|
if (p->dist <= emins[p->type])
|
|
return 1;
|
|
if (p->dist >= emaxs[p->type])
|
|
return 2;
|
|
return 3;
|
|
}
|
|
#endif
|
|
|
|
// general case
|
|
switch (p->signbits)
|
|
{
|
|
case 0:
|
|
dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
|
|
dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
|
|
break;
|
|
case 1:
|
|
dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
|
|
dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
|
|
break;
|
|
case 2:
|
|
dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
|
|
dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
|
|
break;
|
|
case 3:
|
|
dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
|
|
dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
|
|
break;
|
|
case 4:
|
|
dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
|
|
dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
|
|
break;
|
|
case 5:
|
|
dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
|
|
dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
|
|
break;
|
|
case 6:
|
|
dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
|
|
dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
|
|
break;
|
|
case 7:
|
|
dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
|
|
dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
|
|
break;
|
|
default:
|
|
dist1 = dist2 = 0; // shut up compiler
|
|
BOPS_Error ();
|
|
break;
|
|
}
|
|
|
|
#if 0
|
|
int i;
|
|
vec3_t corners[2];
|
|
|
|
for (i=0 ; i<3 ; i++)
|
|
{
|
|
if (plane->normal[i] < 0)
|
|
{
|
|
corners[0][i] = emins[i];
|
|
corners[1][i] = emaxs[i];
|
|
}
|
|
else
|
|
{
|
|
corners[1][i] = emins[i];
|
|
corners[0][i] = emaxs[i];
|
|
}
|
|
}
|
|
dist = DotProduct (plane->normal, corners[0]) - plane->dist;
|
|
dist2 = DotProduct (plane->normal, corners[1]) - plane->dist;
|
|
sides = 0;
|
|
if (dist1 >= 0)
|
|
sides = 1;
|
|
if (dist2 < 0)
|
|
sides |= 2;
|
|
|
|
#endif
|
|
|
|
sides = 0;
|
|
if (dist1 >= p->dist)
|
|
sides = 1;
|
|
if (dist2 < p->dist)
|
|
sides |= 2;
|
|
|
|
#ifdef PARANOID
|
|
if (sides == 0)
|
|
Sys_Error ("BoxOnPlaneSide: sides==0");
|
|
#endif
|
|
|
|
return sides;
|
|
}
|
|
|
|
#ifdef USEFPM
|
|
int BoxOnPlaneSideFPM (vec3_FPM_t emins, vec3_FPM_t emaxs, mplane_FPM_t *p)
|
|
{
|
|
fixedpoint_t dist1, dist2;
|
|
int sides;
|
|
|
|
// general case
|
|
switch (p->signbits)
|
|
{
|
|
case 0:
|
|
dist1 = DotProductFPM(p->normal, emaxs);
|
|
dist2 = DotProductFPM(p->normal, emins);
|
|
break;
|
|
case 1:
|
|
dist1 = FPM_ADD3(FPM_MUL(p->normal[0],emins[0]),FPM_MUL(p->normal[1],emaxs[1]),FPM_MUL(p->normal[2],emaxs[2]));
|
|
dist2 = FPM_ADD3(FPM_MUL(p->normal[0],emaxs[0]),FPM_MUL(p->normal[1],emins[1]),FPM_MUL(p->normal[2],emins[2]));
|
|
break;
|
|
case 2:
|
|
dist1 = FPM_ADD3(FPM_MUL(p->normal[0],emaxs[0]),FPM_MUL(p->normal[1],emins[1]),FPM_MUL(p->normal[2],emaxs[2]));
|
|
dist2 = FPM_ADD3(FPM_MUL(p->normal[0],emins[0]),FPM_MUL(p->normal[1],emaxs[1]),FPM_MUL(p->normal[2],emins[2]));
|
|
break;
|
|
case 3:
|
|
dist1 = FPM_ADD3(FPM_MUL(p->normal[0],emins[0]),FPM_MUL(p->normal[1],emins[1]),FPM_MUL(p->normal[2],emaxs[2]));
|
|
dist2 = FPM_ADD3(FPM_MUL(p->normal[0],emaxs[0]),FPM_MUL(p->normal[1],emaxs[1]),FPM_MUL(p->normal[2],emins[2]));
|
|
break;
|
|
case 4:
|
|
dist1 = FPM_ADD3(FPM_MUL(p->normal[0],emaxs[0]),FPM_MUL(p->normal[1],emaxs[1]),FPM_MUL(p->normal[2],emins[2]));
|
|
dist2 = FPM_ADD3(FPM_MUL(p->normal[0],emins[0]),FPM_MUL(p->normal[1],emins[1]),FPM_MUL(p->normal[2],emaxs[2]));
|
|
break;
|
|
case 5:
|
|
dist1 = FPM_ADD3(FPM_MUL(p->normal[0],emins[0]),FPM_MUL(p->normal[1],emaxs[1]),FPM_MUL(p->normal[2],emins[2]));
|
|
dist2 = FPM_ADD3(FPM_MUL(p->normal[0],emaxs[0]),FPM_MUL(p->normal[1],emins[1]),FPM_MUL(p->normal[2],emaxs[2]));
|
|
break;
|
|
case 6:
|
|
dist1 = FPM_ADD3(FPM_MUL(p->normal[0],emaxs[0]),FPM_MUL(p->normal[1],emins[1]),FPM_MUL(p->normal[2],emins[2]));
|
|
dist2 = FPM_ADD3(FPM_MUL(p->normal[0],emins[0]),FPM_MUL(p->normal[1],emaxs[1]),FPM_MUL(p->normal[2],emaxs[2]));
|
|
break;
|
|
case 7:
|
|
dist1 = FPM_ADD3(FPM_MUL(p->normal[0],emins[0]),FPM_MUL(p->normal[1],emins[1]),FPM_MUL(p->normal[2],emins[2]));
|
|
dist2 = FPM_ADD3(FPM_MUL(p->normal[0],emaxs[0]),FPM_MUL(p->normal[1],emaxs[1]),FPM_MUL(p->normal[2],emaxs[2]));
|
|
break;
|
|
default:
|
|
dist1 = dist2 = 0; // shut up compiler
|
|
BOPS_Error ();
|
|
break;
|
|
}
|
|
|
|
|
|
sides = 0;
|
|
if (dist1 >= p->dist)
|
|
sides = 1;
|
|
if (dist2 < p->dist)
|
|
sides |= 2;
|
|
|
|
#ifdef PARANOID
|
|
if (sides == 0)
|
|
Sys_Error ("BoxOnPlaneSide: sides==0");
|
|
#endif
|
|
|
|
return sides;
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
|
|
void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
|
|
{
|
|
float angle;
|
|
float sr, sp, sy, cr, cp, cy;
|
|
|
|
angle = (float)(angles[YAW] * (M_PI*2 / 360));
|
|
sy = (float)sin(angle);
|
|
cy = (float)cos(angle);
|
|
angle = (float)(angles[PITCH] * (M_PI*2 / 360));
|
|
sp = (float)sin(angle);
|
|
cp = (float)cos(angle);
|
|
angle = (float)(angles[ROLL] * (M_PI*2 / 360));
|
|
sr = (float)sin(angle);
|
|
cr = (float)cos(angle);
|
|
|
|
forward[0] = cp*cy;
|
|
forward[1] = cp*sy;
|
|
forward[2] = -sp;
|
|
right[0] = (-1*sr*sp*cy+-1*cr*-sy);
|
|
right[1] = (-1*sr*sp*sy+-1*cr*cy);
|
|
right[2] = -1*sr*cp;
|
|
up[0] = (cr*sp*cy+-sr*-sy);
|
|
up[1] = (cr*sp*sy+-sr*cy);
|
|
up[2] = cr*cp;
|
|
}
|
|
|
|
#ifdef USEFPM
|
|
void AngleVectorsFPM (vec3_FPM_t angles, vec3_FPM_t forward, vec3_FPM_t right, vec3_FPM_t up)
|
|
{
|
|
double source;
|
|
double angle;
|
|
// fixedpoint_t angle;
|
|
// fixedpoint_t sr, sp, sy, cr, cp, cy;
|
|
__int64 sr, sp, sy, cr, cp, cy;
|
|
register __int64 /*conv, mul,*/ accum1, accum2, accum1b, accum2b;
|
|
|
|
//Dan: ID converted all of these angles to rads for the sin, cos functions.
|
|
//My Fixed Point Math routines can calc trig based on degrees. So this routine
|
|
//is much more efficient than it was before
|
|
|
|
source=FPM_TOFLOAT(FPM_MUL(angles[YAW], FPM_DIV(FPM_PI, FPM_FROMLONGC(180))));
|
|
angle = sin(source);
|
|
sy = (__int64)(angle*(double)(2^32));
|
|
|
|
angle = cos(source);
|
|
cy = (__int64)(angle*(double)(2^32));
|
|
|
|
// sy = FPM_SIN_DEG(angles[YAW]);
|
|
// cy = FPM_COS_DEG(angles[YAW]);
|
|
|
|
source=FPM_TOFLOAT(FPM_MUL(angles[PITCH], FPM_DIV(FPM_PI, FPM_FROMLONGC(180))));
|
|
angle = sin(source);
|
|
sp = (__int64)(angle*(double)(2^32));
|
|
|
|
angle = cos(source);
|
|
cp = (__int64)(angle*(double)(2^32));
|
|
|
|
// angle = angles[PITCH] * (M_PI*2 / 360);
|
|
// sp = FPM_SIN_DEG(angles[PITCH]);
|
|
// cp = FPM_COS_DEG(angles[PITCH]);
|
|
// angle = angles[ROLL] * (M_PI*2 / 360);
|
|
|
|
source=FPM_TOFLOAT(FPM_MUL(angles[ROLL], FPM_DIV(FPM_PI, FPM_FROMLONGC(180))));
|
|
angle = sin(source);
|
|
sr = (__int64)(angle*(double)(2^32));
|
|
|
|
angle = cos(source);
|
|
cr = (__int64)(angle*(double)(2^32));
|
|
|
|
// sr = FPM_SIN_DEG(angles[ROLL]);
|
|
// cr = FPM_COS_DEG(angles[ROLL]);
|
|
|
|
forward[0] = (fixedpoint_t)((cp*cy)>>32); //FPM_MUL(cp,cy);
|
|
forward[1] = (fixedpoint_t)((cp*sy)>>32); //FPM_MUL(cp,sy);
|
|
forward[2] = (fixedpoint_t)((-sp)>>16);
|
|
|
|
accum1=-sr;
|
|
accum2=-sr;
|
|
|
|
accum1*=sp;
|
|
accum2*=sp;
|
|
|
|
accum1*=cy;
|
|
accum2b=cy;
|
|
|
|
accum1b=-cr;
|
|
accum2b*=-cr;
|
|
|
|
accum1b*=-sy;
|
|
accum2*=sy;
|
|
|
|
accum1+=accum1b;
|
|
accum2+=accum2b;
|
|
accum1>>=16;
|
|
accum2>>=16;
|
|
right[0]=(fixedpoint_t)accum1;
|
|
right[1]=(fixedpoint_t)accum2;
|
|
|
|
//right[0] = FPM_ADD(FPM_MUL(FPM_MUL(FPM_MUL(FPM_FROMLONG(-1),sr),sp),cy),FPM_MUL(FPM_MUL(FPM_FROMLONG(-1),cr),-sy));
|
|
//right[0] = (-1*sr*sp*cy+-1*cr*-sy);
|
|
//right[1] = FPM_ADD(FPM_MUL(FPM_MUL(FPM_MUL(FPM_FROMLONG(-1),sr),sp),sy),FPM_MUL(FPM_MUL(FPM_FROMLONG(-1),cr),cy));
|
|
//right[1] = (-1*sr*sp*sy+-1*cr*cy);
|
|
//right[2] = FPM_MUL(FPM_MUL(FPM_FROMLONG(-1),sr),cp);
|
|
accum1=-sr;
|
|
accum1*=cp;
|
|
accum1>>=16;
|
|
right[2]=(fixedpoint_t)accum1;
|
|
|
|
accum1=cr;
|
|
accum1*=sp;
|
|
accum1*=cy;
|
|
accum1b=-sr;
|
|
accum1b*=-sy;
|
|
accum1+=accum1b;
|
|
accum1>>=16;
|
|
up[0] = (fixedpoint_t)accum1;
|
|
//right[2] = -1*sr*cp;
|
|
//up[0] = FPM_ADD(FPM_MUL(FPM_MUL(cr,sp),cy),FPM_MUL(-sr,-sy));
|
|
//up[0] = (cr*sp*cy+-sr*-sy);
|
|
|
|
accum1=cr;
|
|
accum1*=sp;
|
|
accum1*=sy;
|
|
accum1b=-sr;
|
|
accum1b*=cy;
|
|
accum1+=accum1b;
|
|
accum1>>=16;
|
|
up[1]=(fixedpoint_t)accum1;
|
|
|
|
//up[1] = FPM_ADD(FPM_MUL(FPM_MUL(cr,sp),sy),FPM_MUL(-sr,cy));
|
|
//up[1] = (cr*sp*sy+-sr*cy);
|
|
|
|
accum1=cr;
|
|
accum1*=cp;
|
|
accum1>>=16;
|
|
up[2]=(fixedpoint_t)accum1;
|
|
|
|
//up[2] = FPM_MUL(cr,cp);
|
|
//up[2] = cr*cp;
|
|
}
|
|
#endif
|
|
|
|
int VectorCompare (vec3_t v1, vec3_t v2)
|
|
{
|
|
int i;
|
|
|
|
for (i=0 ; i<3 ; i++)
|
|
if (v1[i] != v2[i])
|
|
return 0;
|
|
|
|
return 1;
|
|
}
|
|
|
|
#ifdef USEFPM
|
|
int VectorCompareFPM (vec3_FPM_t v1, vec3_FPM_t v2)
|
|
{
|
|
int i;
|
|
|
|
for (i=0 ; i<3 ; i++)
|
|
if (v1[i] != v2[i])
|
|
return 0;
|
|
|
|
return 1;
|
|
}
|
|
#endif
|
|
|
|
void VectorMA (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc)
|
|
{
|
|
vecc[0] = veca[0] + scale*vecb[0];
|
|
vecc[1] = veca[1] + scale*vecb[1];
|
|
vecc[2] = veca[2] + scale*vecb[2];
|
|
}
|
|
|
|
#ifdef USEFPM
|
|
void VectorMAFPM (vec3_FPM_t veca, fixedpoint_t scale, vec3_FPM_t vecb, vec3_FPM_t vecc)
|
|
{
|
|
vecc[0] = FPM_ADD(veca[0], FPM_MUL(scale, vecb[0]));
|
|
vecc[1] = FPM_ADD(veca[1], FPM_MUL(scale, vecb[1]));
|
|
vecc[2] = FPM_ADD(veca[2], FPM_MUL(scale, vecb[2]));
|
|
}
|
|
#endif
|
|
|
|
//Dan: The following functions do not appear to be used by WinQuake
|
|
/*
|
|
vec_t _DotProduct (vec3_t v1, vec3_t v2)
|
|
{
|
|
return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
|
|
}
|
|
|
|
void _VectorSubtract (vec3_t veca, vec3_t vecb, vec3_t out)
|
|
{
|
|
out[0] = veca[0]-vecb[0];
|
|
out[1] = veca[1]-vecb[1];
|
|
out[2] = veca[2]-vecb[2];
|
|
}
|
|
|
|
void _VectorAdd (vec3_t veca, vec3_t vecb, vec3_t out)
|
|
{
|
|
out[0] = veca[0]+vecb[0];
|
|
out[1] = veca[1]+vecb[1];
|
|
out[2] = veca[2]+vecb[2];
|
|
}
|
|
|
|
void _VectorCopy (vec3_t in, vec3_t out)
|
|
{
|
|
out[0] = in[0];
|
|
out[1] = in[1];
|
|
out[2] = in[2];
|
|
}
|
|
*/
|
|
|
|
void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross)
|
|
{
|
|
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];
|
|
}
|
|
|
|
#ifdef USEFPM
|
|
void CrossProductFPM (vec3_FPM_t v1, vec3_FPM_t v2, vec3_FPM_t cross)
|
|
{
|
|
cross[0] = FPM_SUB(FPM_MUL(v1[1], v2[2]), FPM_MUL(v1[2], v2[1]));
|
|
cross[1] = FPM_SUB(FPM_MUL(v1[2], v2[0]), FPM_MUL(v1[0], v2[2]));
|
|
cross[2] = FPM_SUB(FPM_MUL(v1[0], v2[1]), FPM_MUL(v1[1], v2[0]));
|
|
}
|
|
#endif
|
|
|
|
vec_t Length(vec3_t v)
|
|
{
|
|
int i;
|
|
float length;
|
|
|
|
length = 0;
|
|
for (i=0 ; i< 3 ; i++)
|
|
length += v[i]*v[i];
|
|
length = (float)sqrt (length); // FIXME
|
|
|
|
return length;
|
|
}
|
|
|
|
#ifdef USEFPM
|
|
fixedpoint_t LengthFPM(vec3_FPM_t v)
|
|
{
|
|
int i;
|
|
//Dan: squaring the vectors results in overflow, so we're hardcoding 64 bit 16.16 fixedpoint:
|
|
__int64 length, tmp;
|
|
|
|
// fixedpoint_t length;
|
|
|
|
length = 0;
|
|
for (i=0 ; i< 3 ; i++) {
|
|
tmp=v[i];
|
|
length += (tmp*tmp)>>16;
|
|
}
|
|
return (fixedpoint_t)sqrt (length/65536.0)*65536; // FIXME (not Dan's comment)
|
|
|
|
// return length;
|
|
}
|
|
#endif
|
|
|
|
float VectorNormalize (vec3_t v)
|
|
{
|
|
float length, ilength;
|
|
|
|
length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
|
|
length = (float)sqrt (length); // FIXME
|
|
|
|
if (length)
|
|
{
|
|
ilength = 1/length;
|
|
v[0] *= ilength;
|
|
v[1] *= ilength;
|
|
v[2] *= ilength;
|
|
}
|
|
|
|
return length;
|
|
|
|
}
|
|
|
|
#ifdef USEFPM
|
|
fixedpoint_t VectorNormalizeFPM (vec3_FPM_t v)
|
|
{
|
|
fixedpoint_t length;//, ilength;
|
|
|
|
length = FPM_ADD3(FPM_MUL(v[0],v[0]),FPM_MUL(v[1],v[1]),FPM_MUL(v[2],v[2]));
|
|
length = FPM_SQRT (length); // FIXME (not dan's comment)
|
|
|
|
if (length)
|
|
{
|
|
//ilength = FPM_INV(length);
|
|
v[0]=FPM_DIV(v[0], length); //FPM_MUL(v[0], ilength);
|
|
v[1]=FPM_DIV(v[1], length); //FPM_MUL(v[1], ilength);
|
|
v[2]=FPM_DIV(v[2], length); //FPM_MUL(v[2], ilength);
|
|
}
|
|
|
|
return length;
|
|
|
|
}
|
|
#endif
|
|
|
|
void VectorInverse (vec3_t v)
|
|
{
|
|
v[0] = -v[0];
|
|
v[1] = -v[1];
|
|
v[2] = -v[2];
|
|
}
|
|
|
|
#ifdef USEFPM
|
|
void VectorInverseFPM (vec3_FPM_t v)
|
|
{
|
|
v[0] = -v[0];
|
|
v[1] = -v[1];
|
|
v[2] = -v[2];
|
|
}
|
|
#endif
|
|
|
|
void VectorScale (vec3_t in, vec_t scale, vec3_t out)
|
|
{
|
|
out[0] = in[0]*scale;
|
|
out[1] = in[1]*scale;
|
|
out[2] = in[2]*scale;
|
|
}
|
|
|
|
#ifdef USEFPM
|
|
void VectorScaleFPM (vec3_FPM_t in, fixedpoint_t scale, vec3_FPM_t out)
|
|
{
|
|
out[0] = FPM_MUL(in[0], scale);
|
|
out[1] = FPM_MUL(in[1], scale);
|
|
out[2] = FPM_MUL(in[2], scale);
|
|
}
|
|
#endif
|
|
|
|
int Q_log2(int val)
|
|
{
|
|
int answer=0;
|
|
while (val>>=1)
|
|
answer++;
|
|
return answer;
|
|
}
|
|
|
|
|
|
/*
|
|
================
|
|
R_ConcatRotations
|
|
================
|
|
*/
|
|
void R_ConcatRotations (float in1[3][3], float in2[3][3], float out[3][3])
|
|
{
|
|
out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] +
|
|
in1[0][2] * in2[2][0];
|
|
out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] +
|
|
in1[0][2] * in2[2][1];
|
|
out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] +
|
|
in1[0][2] * in2[2][2];
|
|
out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] +
|
|
in1[1][2] * in2[2][0];
|
|
out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] +
|
|
in1[1][2] * in2[2][1];
|
|
out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] +
|
|
in1[1][2] * in2[2][2];
|
|
out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] +
|
|
in1[2][2] * in2[2][0];
|
|
out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] +
|
|
in1[2][2] * in2[2][1];
|
|
out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] +
|
|
in1[2][2] * in2[2][2];
|
|
}
|
|
|
|
#ifdef USEFPM
|
|
void R_ConcatRotationsFPM (fixedpoint_t in1[3][3], fixedpoint_t in2[3][3], fixedpoint_t out[3][3])
|
|
{
|
|
out[0][0] = FPM_ADD3(FPM_MUL(in1[0][0],in2[0][0]), FPM_MUL(in1[0][1],in2[1][0]),
|
|
FPM_MUL(in1[0][2],in2[2][0]));
|
|
out[0][1] = FPM_ADD3(FPM_MUL(in1[0][0],in2[0][1]), FPM_MUL(in1[0][1],in2[1][1]),
|
|
FPM_MUL(in1[0][2],in2[2][1]));
|
|
out[0][2] = FPM_ADD3(FPM_MUL(in1[0][0],in2[0][2]), FPM_MUL(in1[0][1],in2[1][2]),
|
|
FPM_MUL(in1[0][2],in2[2][2]));
|
|
out[1][0] = FPM_ADD3(FPM_MUL(in1[1][0],in2[0][0]), FPM_MUL(in1[1][1],in2[1][0]),
|
|
FPM_MUL(in1[1][2],in2[2][0]));
|
|
out[1][1] = FPM_ADD3(FPM_MUL(in1[1][0],in2[0][1]), FPM_MUL(in1[1][1],in2[1][1]),
|
|
FPM_MUL(in1[1][2],in2[2][1]));
|
|
out[1][2] = FPM_ADD3(FPM_MUL(in1[1][0],in2[0][2]), FPM_MUL(in1[1][1],in2[1][2]),
|
|
FPM_MUL(in1[1][2],in2[2][2]));
|
|
out[2][0] = FPM_ADD3(FPM_MUL(in1[2][0],in2[0][0]), FPM_MUL(in1[2][1],in2[1][0]),
|
|
FPM_MUL(in1[2][2],in2[2][0]));
|
|
out[2][1] = FPM_ADD3(FPM_MUL(in1[2][0],in2[0][1]), FPM_MUL(in1[2][1],in2[1][1]),
|
|
FPM_MUL(in1[2][2],in2[2][1]));
|
|
out[2][2] = FPM_ADD3(FPM_MUL(in1[2][0],in2[0][2]), FPM_MUL(in1[2][1],in2[1][2]),
|
|
FPM_MUL(in1[2][2],in2[2][2]));
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
================
|
|
R_ConcatTransforms
|
|
================
|
|
*/
|
|
void R_ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4])
|
|
{
|
|
out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] +
|
|
in1[0][2] * in2[2][0];
|
|
out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] +
|
|
in1[0][2] * in2[2][1];
|
|
out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] +
|
|
in1[0][2] * in2[2][2];
|
|
out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] +
|
|
in1[0][2] * in2[2][3] + in1[0][3];
|
|
out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] +
|
|
in1[1][2] * in2[2][0];
|
|
out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] +
|
|
in1[1][2] * in2[2][1];
|
|
out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] +
|
|
in1[1][2] * in2[2][2];
|
|
out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] +
|
|
in1[1][2] * in2[2][3] + in1[1][3];
|
|
out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] +
|
|
in1[2][2] * in2[2][0];
|
|
out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] +
|
|
in1[2][2] * in2[2][1];
|
|
out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] +
|
|
in1[2][2] * in2[2][2];
|
|
out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] +
|
|
in1[2][2] * in2[2][3] + in1[2][3];
|
|
}
|
|
|
|
#ifdef USEFPM
|
|
void R_ConcatTransformsFPM (fixedpoint_t in1[3][4], fixedpoint_t in2[3][4], fixedpoint_t out[3][4])
|
|
{
|
|
register __int64 accum, mul;
|
|
int i;
|
|
for (i=0; i<3; i++) {
|
|
accum=in1[i][0];
|
|
accum*=in2[0][0];
|
|
mul=in1[i][1];
|
|
mul*=in2[1][0];
|
|
accum+=mul;
|
|
mul=in1[i][2];
|
|
mul*=in2[2][0];
|
|
accum+=mul;
|
|
accum>>=16;
|
|
out[i][0]=(fixedpoint_t)accum;
|
|
|
|
accum=in1[i][0];
|
|
accum*=in2[0][1];
|
|
mul=in1[i][1];
|
|
mul*=in2[1][1];
|
|
accum+=mul;
|
|
mul=in1[i][2];
|
|
mul*=in2[2][1];
|
|
accum+=mul;
|
|
accum>>=16;
|
|
out[i][1]=(fixedpoint_t)accum;
|
|
|
|
accum=in1[i][0];
|
|
accum*=in2[0][2];
|
|
mul=in1[i][1];
|
|
mul*=in2[1][2];
|
|
accum+=mul;
|
|
mul=in1[i][2];
|
|
mul*=in2[2][2];
|
|
accum+=mul;
|
|
accum>>=16;
|
|
out[i][2]=(fixedpoint_t)accum;
|
|
|
|
accum=in1[i][0];
|
|
accum*=in2[0][3];
|
|
mul=in1[i][1];
|
|
mul*=in2[1][3];
|
|
accum+=mul;
|
|
mul=in1[i][2];
|
|
mul*=in2[2][3];
|
|
accum+=mul;
|
|
mul=in1[0][3];
|
|
mul<<=16; //16.16 -> 32.32
|
|
accum+=mul;
|
|
accum>>=16;
|
|
out[i][3]=(fixedpoint_t)accum;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
void R_ConcatTransformsFPM (fixedpoint_t in1[3][4], fixedpoint_t in2[3][4], fixedpoint_t out[3][4])
|
|
{
|
|
out[0][0] = FPM_ADD3(FPM_MUL(in1[0][0],in2[0][0]),FPM_MUL(in1[0][1],in2[1][0]),
|
|
FPM_MUL(in1[0][2],in2[2][0]));
|
|
out[0][1] = FPM_ADD3(FPM_MUL(in1[0][0],in2[0][1]),FPM_MUL(in1[0][1],in2[1][1]),
|
|
FPM_MUL(in1[0][2],in2[2][1]));
|
|
out[0][2] = FPM_ADD3(FPM_MUL(in1[0][0],in2[0][2]),FPM_MUL(in1[0][1],in2[1][2]),
|
|
FPM_MUL(in1[0][2],in2[2][2]));
|
|
out[0][3] = FPM_ADD(FPM_ADD3(FPM_MUL(in1[0][0],in2[0][3]),FPM_MUL(in1[0][1],in2[1][3]),
|
|
FPM_MUL(in1[0][2],in2[2][3])),in1[0][3]);
|
|
out[1][0] = FPM_ADD3(FPM_MUL(in1[1][0],in2[0][0]),FPM_MUL(in1[1][1],in2[1][0]),
|
|
FPM_MUL(in1[1][2],in2[2][0]));
|
|
out[1][1] = FPM_ADD3(FPM_MUL(in1[1][0],in2[0][1]),FPM_MUL(in1[1][1],in2[1][1]),
|
|
FPM_MUL(in1[1][2],in2[2][1]));
|
|
out[1][2] = FPM_ADD3(FPM_MUL(in1[1][0],in2[0][2]),FPM_MUL(in1[1][1],in2[1][2]),
|
|
FPM_MUL(in1[1][2],in2[2][2]));
|
|
out[1][3] = FPM_ADD(FPM_ADD3(FPM_MUL(in1[1][0],in2[0][3]),FPM_MUL(in1[1][1],in2[1][3]),
|
|
FPM_MUL(in1[1][2],in2[2][3])),in1[1][3]);
|
|
out[2][0] = FPM_ADD3(FPM_MUL(in1[2][0],in2[0][0]),FPM_MUL(in1[2][1],in2[1][0]),
|
|
FPM_MUL(in1[2][2],in2[2][0]));
|
|
out[2][1] = FPM_ADD3(FPM_MUL(in1[2][0],in2[0][1]),FPM_MUL(in1[2][1],in2[1][1]),
|
|
FPM_MUL(in1[2][2],in2[2][1]));
|
|
out[2][2] = FPM_ADD3(FPM_MUL(in1[2][0],in2[0][2]),FPM_MUL(in1[2][1],in2[1][2]),
|
|
FPM_MUL(in1[2][2],in2[2][2]));
|
|
out[2][3] = FPM_ADD(FPM_ADD3(FPM_MUL(in1[2][0],in2[0][3]),FPM_MUL(in1[2][1],in2[1][3]),
|
|
FPM_MUL(in1[2][2],in2[2][3])),in1[2][3]);
|
|
}
|
|
*/
|
|
|
|
#ifdef USEFPM
|
|
void R_ConcatTransforms8_24FPM (fixedpoint_t in1[3][4], fixedpoint_t in2[3][4], fixedpoint8_24_t out[3][4])
|
|
{
|
|
int i;
|
|
register __int64 accum, i1, i2, i3, conv;
|
|
|
|
for (i=0; i<3; i++) {
|
|
accum=0;
|
|
i1=in1[i][0];
|
|
i1<<=16;
|
|
i2=in1[i][1];
|
|
i2<<=16;
|
|
i3=in1[i][2];
|
|
i3<<=16;
|
|
|
|
conv=in2[0][0];
|
|
conv<<=16;
|
|
conv*=i1;
|
|
accum=conv>>16;
|
|
conv=in2[1][0];
|
|
conv<<=16;
|
|
conv*=i2;
|
|
accum+=conv>>16;
|
|
conv=in2[2][0];
|
|
conv<<=16;
|
|
conv*=i3;
|
|
accum+=conv>>16;
|
|
out[i][0] = (fixedpoint8_24_t)accum>>8;
|
|
|
|
conv=in2[0][1];
|
|
conv<<=16;
|
|
conv*=i1;
|
|
accum=conv>>16;
|
|
conv=in2[1][1];
|
|
conv<<=16;
|
|
conv*=i2;
|
|
accum+=conv>>16;
|
|
conv=in2[2][1];
|
|
conv<<=16;
|
|
conv*=i3;
|
|
accum+=conv>>16;
|
|
out[i][1] = (fixedpoint8_24_t)accum>>8;
|
|
|
|
conv=in2[0][2];
|
|
conv<<=16;
|
|
conv*=i1;
|
|
accum=conv>>16;
|
|
conv=in2[1][2];
|
|
conv<<=16;
|
|
conv*=i2;
|
|
accum+=conv>>16;
|
|
conv=in2[2][2];
|
|
conv<<=16;
|
|
conv*=i3;
|
|
accum+=conv>>16;
|
|
out[i][2] = (fixedpoint8_24_t)accum>>8; //to 8.24
|
|
|
|
conv=in2[0][3];
|
|
conv<<=16;
|
|
conv*=i1;
|
|
accum=conv>>16;
|
|
conv=in2[1][3];
|
|
conv<<=16;
|
|
conv*=i2;
|
|
accum+=conv>>16;
|
|
conv=in2[2][3];
|
|
conv<<=16;
|
|
conv*=i3;
|
|
accum+=conv>>16;
|
|
conv=in1[0][3];
|
|
conv<<=16;
|
|
accum+=conv;
|
|
out[i][3] = (fixedpoint8_24_t)accum>>16; //to 16.16
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
void R_ConcatTransforms8_24FPM (fixedpoint_t in1[3][4], fixedpoint_t in2[3][4], fixedpoint8_24_t out[3][4])
|
|
{
|
|
out[0][0] = fpm_FromFixedPoint(FPM_ADD3(FPM_MUL(in1[0][0],in2[0][0]),FPM_MUL(in1[0][1],in2[1][0]),
|
|
FPM_MUL(in1[0][2],in2[2][0])));
|
|
out[0][1] = fpm_FromFixedPoint(FPM_ADD3(FPM_MUL(in1[0][0],in2[0][1]),FPM_MUL(in1[0][1],in2[1][1]),
|
|
FPM_MUL(in1[0][2],in2[2][1])));
|
|
out[0][2] = fpm_FromFixedPoint(FPM_ADD3(FPM_MUL(in1[0][0],in2[0][2]),FPM_MUL(in1[0][1],in2[1][2]),
|
|
FPM_MUL(in1[0][2],in2[2][2])));
|
|
out[0][3] = (fixedpoint_t)FPM_ADD(FPM_ADD3(FPM_MUL(in1[0][0],in2[0][3]),FPM_MUL(in1[0][1],in2[1][3]),
|
|
FPM_MUL(in1[0][2],in2[2][3])),in1[0][3]);
|
|
out[1][0] = fpm_FromFixedPoint(FPM_ADD3(FPM_MUL(in1[1][0],in2[0][0]),FPM_MUL(in1[1][1],in2[1][0]),
|
|
FPM_MUL(in1[1][2],in2[2][0])));
|
|
out[1][1] = fpm_FromFixedPoint(FPM_ADD3(FPM_MUL(in1[1][0],in2[0][1]),FPM_MUL(in1[1][1],in2[1][1]),
|
|
FPM_MUL(in1[1][2],in2[2][1])));
|
|
out[1][2] = fpm_FromFixedPoint(FPM_ADD3(FPM_MUL(in1[1][0],in2[0][2]),FPM_MUL(in1[1][1],in2[1][2]),
|
|
FPM_MUL(in1[1][2],in2[2][2])));
|
|
out[1][3] = (fixedpoint_t)FPM_ADD(FPM_ADD3(FPM_MUL(in1[1][0],in2[0][3]),FPM_MUL(in1[1][1],in2[1][3]),
|
|
FPM_MUL(in1[1][2],in2[2][3])),in1[1][3]);
|
|
out[2][0] = fpm_FromFixedPoint(FPM_ADD3(FPM_MUL(in1[2][0],in2[0][0]),FPM_MUL(in1[2][1],in2[1][0]),
|
|
FPM_MUL(in1[2][2],in2[2][0])));
|
|
out[2][1] = fpm_FromFixedPoint(FPM_ADD3(FPM_MUL(in1[2][0],in2[0][1]),FPM_MUL(in1[2][1],in2[1][1]),
|
|
FPM_MUL(in1[2][2],in2[2][1])));
|
|
out[2][2] = fpm_FromFixedPoint(FPM_ADD3(FPM_MUL(in1[2][0],in2[0][2]),FPM_MUL(in1[2][1],in2[1][2]),
|
|
FPM_MUL(in1[2][2],in2[2][2])));
|
|
out[2][3] = (fixedpoint_t)FPM_ADD(FPM_ADD3(FPM_MUL(in1[2][0],in2[0][3]),FPM_MUL(in1[2][1],in2[1][3]),
|
|
FPM_MUL(in1[2][2],in2[2][3])),in1[2][3]);
|
|
}
|
|
*/
|
|
|
|
/*
|
|
===================
|
|
FloorDivMod
|
|
|
|
Returns mathematically correct (floor-based) quotient and remainder for
|
|
numer and denom, both of which should contain no fractional part. The
|
|
quotient must fit in 32 bits.
|
|
====================
|
|
*/
|
|
|
|
void FloorDivMod (double numer, double denom, int *quotient,
|
|
int *rem)
|
|
{
|
|
int q, r;
|
|
double x;
|
|
|
|
#ifndef PARANOID
|
|
if (denom <= 0.0)
|
|
Sys_Error ("FloorDivMod: bad denominator %d\n", denom);
|
|
|
|
// if ((floor(numer) != numer) || (floor(denom) != denom))
|
|
// Sys_Error ("FloorDivMod: non-integer numer or denom %f %f\n",
|
|
// numer, denom);
|
|
#endif
|
|
|
|
if (numer >= 0.0)
|
|
{
|
|
|
|
x = floor(numer / denom);
|
|
q = (int)x;
|
|
r = (int)floor(numer - (x * denom));
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// perform operations with positive values, and fix mod to make floor-based
|
|
//
|
|
x = floor(-numer / denom);
|
|
q = -(int)x;
|
|
r = (int)floor(-numer - (x * denom));
|
|
if (r != 0)
|
|
{
|
|
q--;
|
|
r = (int)denom - r;
|
|
}
|
|
}
|
|
|
|
*quotient = q;
|
|
*rem = r;
|
|
}
|
|
|
|
|
|
/*
|
|
===================
|
|
GreatestCommonDivisor
|
|
====================
|
|
*/
|
|
int GreatestCommonDivisor (int i1, int i2)
|
|
{
|
|
if (i1 > i2)
|
|
{
|
|
if (i2 == 0)
|
|
return (i1);
|
|
return GreatestCommonDivisor (i2, i1 % i2);
|
|
}
|
|
else
|
|
{
|
|
if (i1 == 0)
|
|
return (i2);
|
|
return GreatestCommonDivisor (i1, i2 % i1);
|
|
}
|
|
}
|
|
|
|
|
|
#if !id386
|
|
|
|
// TODO: move to nonintel.c
|
|
|
|
/*
|
|
===================
|
|
Invert24To16
|
|
|
|
Inverts an 8.24 value to a 16.16 value
|
|
====================
|
|
*/
|
|
|
|
fixed16_t Invert24To16(fixed16_t val)
|
|
{
|
|
if (val < 256)
|
|
return (0xFFFFFFFF);
|
|
|
|
return (fixed16_t)
|
|
(((double)0x10000 * (double)0x1000000 / (double)val) + 0.5);
|
|
}
|
|
|
|
int ParseFloats(char *s, float *f, int *f_size) {
|
|
int i, argc;
|
|
|
|
if (!s || !f || !f_size)
|
|
Sys_Error("ParseFloats() wrong params");
|
|
|
|
if (f_size[0] <= 0)
|
|
return (f_size[0] = 0);
|
|
|
|
Cmd_TokenizeString(s);
|
|
// argc = min(Cmd_Argc(), f_size[0]);
|
|
argc = (Cmd_Argc(), f_size[0]);
|
|
|
|
for(i = 0; i < argc; i++)
|
|
f[i] = Q_atof(Cmd_Argv(i));
|
|
|
|
for( ; i < f_size[0]; i++)
|
|
f[i] = 0;
|
|
|
|
return (f_size[0] = argc);
|
|
}
|
|
|
|
#endif
|