halflife-photomode/pm_shared/pm_math.cpp

423 lines
8.6 KiB
C++
Raw Normal View History

/***
2013-08-30 13:34:05 -07: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
#include "Platform.h"
2013-08-30 13:34:05 -07:00
#include "mathlib.h"
#include "const.h"
// up / down
#define PITCH 0
2013-08-30 13:34:05 -07:00
// left / right
#define YAW 1
2013-08-30 13:34:05 -07:00
// fall over
#define ROLL 2
2013-08-30 13:34:05 -07:00
#pragma warning(disable : 4244)
int nanmask = 255 << 23;
2013-08-30 13:34:05 -07:00
float anglemod(float a)
2013-08-30 13:34:05 -07:00
{
a = (360.0 / 65536) * ((int)(a * (65536 / 360.0)) & 65535);
2013-08-30 13:34:05 -07:00
return a;
}
void AngleVectors(const Vector& angles, Vector* forward, Vector* right, Vector* up)
2013-08-30 13:34:05 -07:00
{
float angle;
float sr, sp, sy, cr, cp, cy;
angle = angles[YAW] * (M_PI * 2 / 360);
2013-08-30 13:34:05 -07:00
sy = sin(angle);
cy = cos(angle);
angle = angles[PITCH] * (M_PI * 2 / 360);
2013-08-30 13:34:05 -07:00
sp = sin(angle);
cp = cos(angle);
angle = angles[ROLL] * (M_PI * 2 / 360);
2013-08-30 13:34:05 -07:00
sr = sin(angle);
cr = cos(angle);
if (forward)
{
forward->x = cp * cy;
forward->y = cp * sy;
forward->z = -sp;
2013-08-30 13:34:05 -07:00
}
if (right)
{
right->x = (-1 * sr * sp * cy + -1 * cr * -sy);
right->y = (-1 * sr * sp * sy + -1 * cr * cy);
right->z = -1 * sr * cp;
2013-08-30 13:34:05 -07:00
}
if (up)
{
up->x = (cr * sp * cy + -sr * -sy);
up->y = (cr * sp * sy + -sr * cy);
up->z = cr * cp;
2013-08-30 13:34:05 -07:00
}
}
void AngleVectorsTranspose(const Vector& angles, Vector* forward, Vector* right, Vector* up)
2013-08-30 13:34:05 -07:00
{
float angle;
float sr, sp, sy, cr, cp, cy;
angle = angles[YAW] * (M_PI * 2 / 360);
2013-08-30 13:34:05 -07:00
sy = sin(angle);
cy = cos(angle);
angle = angles[PITCH] * (M_PI * 2 / 360);
2013-08-30 13:34:05 -07:00
sp = sin(angle);
cp = cos(angle);
angle = angles[ROLL] * (M_PI * 2 / 360);
2013-08-30 13:34:05 -07:00
sr = sin(angle);
cr = cos(angle);
if (forward)
{
forward->x = cp * cy;
forward->y = (sr * sp * cy + cr * -sy);
forward->z = (cr * sp * cy + -sr * -sy);
2013-08-30 13:34:05 -07:00
}
if (right)
{
right->x = cp * sy;
right->y = (sr * sp * sy + cr * cy);
right->z = (cr * sp * sy + -sr * cy);
2013-08-30 13:34:05 -07:00
}
if (up)
{
up->x = -sp;
up->y = sr * cp;
up->z = cr * cp;
2013-08-30 13:34:05 -07:00
}
}
void AngleMatrix(const float* angles, float (*matrix)[4])
2013-08-30 13:34:05 -07:00
{
float angle;
float sr, sp, sy, cr, cp, cy;
angle = angles[YAW] * (M_PI * 2 / 360);
2013-08-30 13:34:05 -07:00
sy = sin(angle);
cy = cos(angle);
angle = angles[PITCH] * (M_PI * 2 / 360);
2013-08-30 13:34:05 -07:00
sp = sin(angle);
cp = cos(angle);
angle = angles[ROLL] * (M_PI * 2 / 360);
2013-08-30 13:34:05 -07:00
sr = sin(angle);
cr = cos(angle);
// matrix = (YAW * PITCH) * ROLL
matrix[0][0] = cp * cy;
matrix[1][0] = cp * sy;
2013-08-30 13:34:05 -07:00
matrix[2][0] = -sp;
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;
2013-08-30 13:34:05 -07:00
matrix[0][3] = 0.0;
matrix[1][3] = 0.0;
matrix[2][3] = 0.0;
}
void AngleIMatrix(const Vector& angles, float matrix[3][4])
2013-08-30 13:34:05 -07:00
{
float angle;
float sr, sp, sy, cr, cp, cy;
angle = angles[YAW] * (M_PI * 2 / 360);
2013-08-30 13:34:05 -07:00
sy = sin(angle);
cy = cos(angle);
angle = angles[PITCH] * (M_PI * 2 / 360);
2013-08-30 13:34:05 -07:00
sp = sin(angle);
cp = cos(angle);
angle = angles[ROLL] * (M_PI * 2 / 360);
2013-08-30 13:34:05 -07:00
sr = sin(angle);
cr = cos(angle);
// matrix = (YAW * PITCH) * ROLL
matrix[0][0] = cp * cy;
matrix[0][1] = cp * sy;
2013-08-30 13:34:05 -07:00
matrix[0][2] = -sp;
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;
2013-08-30 13:34:05 -07:00
matrix[0][3] = 0.0;
matrix[1][3] = 0.0;
matrix[2][3] = 0.0;
}
void NormalizeAngles(float* angles)
2013-08-30 13:34:05 -07:00
{
int i;
// Normalize angles
for (i = 0; i < 3; i++)
2013-08-30 13:34:05 -07:00
{
if (angles[i] > 180.0)
2013-08-30 13:34:05 -07:00
{
angles[i] -= 360.0;
}
else if (angles[i] < -180.0)
2013-08-30 13:34:05 -07:00
{
angles[i] += 360.0;
}
}
}
/*
===================
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)
2013-08-30 13:34:05 -07:00
{
int i;
float ang1, ang2;
float d;
NormalizeAngles(start);
NormalizeAngles(end);
for (i = 0; i < 3; i++)
2013-08-30 13:34:05 -07:00
{
ang1 = start[i];
ang2 = end[i];
d = ang2 - ang1;
if (d > 180)
2013-08-30 13:34:05 -07:00
{
d -= 360;
}
else if (d < -180)
{
2013-08-30 13:34:05 -07:00
d += 360;
}
output[i] = ang1 + d * frac;
}
NormalizeAngles(output);
2013-08-30 13:34:05 -07:00
}
2013-08-30 13:34:05 -07:00
/*
===================
AngleBetweenVectors
===================
*/
float AngleBetweenVectors(const Vector& v1, const Vector& v2)
2013-08-30 13:34:05 -07:00
{
float angle;
float l1 = Length(v1);
float l2 = Length(v2);
2013-08-30 13:34:05 -07:00
if (0 == l1 || 0 == l2)
2013-08-30 13:34:05 -07:00
return 0.0f;
angle = acos(DotProduct(v1, v2)) / (l1 * l2);
angle = (angle * 180.0f) / M_PI;
2013-08-30 13:34:05 -07:00
return angle;
}
void VectorTransform(const float* in1, float in2[3][4], float* out)
2013-08-30 13:34:05 -07:00
{
out[0] = DotProduct(*reinterpret_cast<const Vector*>(in1), *reinterpret_cast<const Vector*>(in2[0])) + in2[0][3];
out[1] = DotProduct(*reinterpret_cast<const Vector*>(in1), *reinterpret_cast<const Vector*>(in2[1])) + in2[1][3];
out[2] = DotProduct(*reinterpret_cast<const Vector*>(in1), *reinterpret_cast<const Vector*>(in2[2])) + in2[2][3];
2013-08-30 13:34:05 -07:00
}
bool VectorCompare(const float* v1, const float* v2)
2013-08-30 13:34:05 -07:00
{
int i;
for (i = 0; i < 3; i++)
2013-08-30 13:34:05 -07:00
if (v1[i] != v2[i])
return false;
return true;
2013-08-30 13:34:05 -07:00
}
void VectorMA(const float* veca, float scale, const float* vecb, float* vecc)
2013-08-30 13:34:05 -07:00
{
vecc[0] = veca[0] + scale * vecb[0];
vecc[1] = veca[1] + scale * vecb[1];
vecc[2] = veca[2] + scale * vecb[2];
2013-08-30 13:34:05 -07:00
}
void CrossProduct(const float* v1, const float* v2, float* cross)
2013-08-30 13:34:05 -07: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];
2013-08-30 13:34:05 -07:00
}
float Length(const float* v)
2013-08-30 13:34:05 -07:00
{
int i;
float length = 0.0f;
for (i = 0; i < 3; i++)
length += v[i] * v[i];
length = sqrt(length); // FIXME
2013-08-30 13:34:05 -07:00
return length;
}
float Distance(const float* v1, const float* v2)
2013-08-30 13:34:05 -07:00
{
Vector d;
VectorSubtract(v2, v1, d);
2013-08-30 13:34:05 -07:00
return Length(d);
}
float VectorNormalize(float* v)
2013-08-30 13:34:05 -07:00
{
float length, ilength;
2013-08-30 13:34:05 -07:00
length = v[0] * v[0] + v[1] * v[1] + v[2] * v[2];
length = sqrt(length); // FIXME
2013-08-30 13:34:05 -07:00
if (0 != length)
2013-08-30 13:34:05 -07:00
{
ilength = 1 / length;
2013-08-30 13:34:05 -07:00
v[0] *= ilength;
v[1] *= ilength;
v[2] *= ilength;
}
return length;
2013-08-30 13:34:05 -07:00
}
void VectorInverse(float* v)
2013-08-30 13:34:05 -07:00
{
v[0] = -v[0];
v[1] = -v[1];
v[2] = -v[2];
}
void VectorScale(const float* in, float scale, float* out)
2013-08-30 13:34:05 -07:00
{
out[0] = in[0] * scale;
out[1] = in[1] * scale;
out[2] = in[2] * scale;
2013-08-30 13:34:05 -07:00
}
int Q_log2(int val)
{
int answer = 0;
while ((val >>= 1) != 0)
2013-08-30 13:34:05 -07:00
answer++;
return answer;
}
void VectorMatrix(const Vector& forward, Vector& right, Vector& up)
2013-08-30 13:34:05 -07:00
{
Vector tmp;
2013-08-30 13:34:05 -07:00
if (forward[0] == 0 && forward[1] == 0)
{
right[0] = 1;
right[1] = 0;
2013-08-30 13:34:05 -07:00
right[2] = 0;
up[0] = -forward[2];
up[1] = 0;
2013-08-30 13:34:05 -07:00
up[2] = 0;
return;
}
tmp[0] = 0;
tmp[1] = 0;
tmp[2] = 1.0;
CrossProduct(forward, tmp, right);
VectorNormalize(right);
CrossProduct(right, forward, up);
VectorNormalize(up);
2013-08-30 13:34:05 -07:00
}
void VectorAngles(const float* forward, float* angles)
2013-08-30 13:34:05 -07:00
{
double tmp, yaw, pitch;
2013-08-30 13:34:05 -07:00
if (forward[1] == 0 && forward[0] == 0)
{
yaw = 0;
if (forward[2] > 0)
pitch = 90;
else
pitch = 270;
}
else
{
yaw = (atan2(forward[1], forward[0]) * 180 / M_PI);
if (yaw < 0)
yaw += 360;
tmp = sqrt(forward[0] * forward[0] + forward[1] * forward[1]);
2013-08-30 13:34:05 -07:00
pitch = (atan2(forward[2], tmp) * 180 / M_PI);
if (pitch < 0)
pitch += 360;
}
2013-08-30 13:34:05 -07:00
angles[0] = pitch;
angles[1] = yaw;
angles[2] = 0;
}
/*
================
ConcatTransforms
================
*/
void 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];
}