267 lines
7.1 KiB
C
267 lines
7.1 KiB
C
#ifndef __FIXED_H__
|
|
#define __FIXED_H__
|
|
|
|
#include <math.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#ifndef PI
|
|
#define PI (3.1415926535897932384626433832795028841971693993751)
|
|
#endif
|
|
|
|
/* Default table size for precomputed sincos table */
|
|
#define FA_TABLE_SIZE 360
|
|
|
|
/*
|
|
Flags for initialization
|
|
FA_CARTESIAN_Y - Y axis is positive up
|
|
*/
|
|
#define FA_DEFAULT 0
|
|
#define FA_CARTESIAN_Y 1
|
|
|
|
#if defined(FX_DOUBLE) || defined(FX_SINGLE)
|
|
|
|
#ifdef FX_DOUBLE
|
|
typedef double FxValue;
|
|
|
|
#define FX_MAX_VALUE (1e100)
|
|
#define FX_MIN_VALUE (1e-10)
|
|
#else
|
|
typedef float FxValue;
|
|
|
|
#define FX_MAX_VALUE (1e38f)
|
|
#define FX_MIN_VALUE (1e-7f)
|
|
#endif
|
|
|
|
#define FxVal(i) ((FxValue)(i))
|
|
#define FxInt(v) ((int)(v))
|
|
#define FxFltVal(f) ((FxValue)(f))
|
|
#define FxFlt(v) ((double)(v))
|
|
#define FxPromote(v) (v)
|
|
#define FxDemote(v) (v)
|
|
|
|
#define FxMul(a, b) ((a)*(b))
|
|
#define FxDemotedMul(a, b) FxMul(a, b)
|
|
#define FxDiv(a, b) ((a)/(b))
|
|
#define FxDemotedDiv(a, b) FxDiv(a, b)
|
|
#define FxMulToInt(a, b) FxInt((a)*(b))
|
|
#define FxDivToInt(a, b) ((int)((a)/(b)))
|
|
#define FxMulDiv(a, m, d) (((a)*(m))/(d))
|
|
#define FxSqrt(v) ((FxValue)sqrt((double)(v)))
|
|
#define FxDemotedSqrt(v) FxSqrt(v)
|
|
|
|
typedef FxValue FaAngle;
|
|
|
|
#define FaAng(a) (a)
|
|
|
|
#define FaSin(v) ((FxValue)-sin((double)(v)))
|
|
#define FaCos(v) ((FxValue)cos((double)(v)))
|
|
|
|
#define FaAdd(a, d) ((a)+(d))
|
|
FaAngle FaNorm(FaAngle a);
|
|
#define FaDeg(da) ((da)*(FxValue)(PI/180.0))
|
|
#define FaRad(ra) (ra)
|
|
#define FaAngVal(aa) (aa)
|
|
#define FaFltDegVal(a) ((a)*180.0/PI)
|
|
#define FaFltRadVal(a) (a)
|
|
|
|
#define FxInitialize(table_size, flags) ((flags) == FA_DEFAULT)
|
|
#define FxEnd()
|
|
|
|
#else
|
|
|
|
/* If integer sqrt isn't interesting, define FX_PRECISE_SQRT
|
|
and the floating point sqrt will be used */
|
|
|
|
#ifndef FX_SHIFT
|
|
#define FX_SHIFT 10
|
|
#endif
|
|
#define FX_MULT (1L << FX_SHIFT)
|
|
|
|
typedef long FxValue;
|
|
|
|
#define FX_MAX_VALUE (0x7fffffff)
|
|
#define FX_MIN_VALUE (1)
|
|
|
|
#define FxVal(i) FxPromote((FxValue)(i))
|
|
#define FxInt(v) ((int)FxDemote(v))
|
|
#define FxFltVal(f) ((FxValue)((f)*(double)FX_MULT))
|
|
#define FxFlt(v) (((double)(v))/(double)FX_MULT)
|
|
#define FxPromote(v) ((v) << FX_SHIFT)
|
|
#define FxDemote(v) ((v) >> FX_SHIFT)
|
|
|
|
#if FX_SHIFT != 16
|
|
/* These can overflow if the shift and numbers are too large */
|
|
#define FxMul(a, b) FxDemote((a)*(b))
|
|
#define FxDiv(a, b) (FxPromote(a)/(b))
|
|
#define FxMulToInt(a, b) FxInt(FxDemote((a)*(b)))
|
|
#define FxMulDiv(a, m, d) (((a)*(m))/(d))
|
|
#else
|
|
/* For FX_SHIFT == 16 and certain platforms, assembly routines are
|
|
provided which do 64-bit intermediate math, preserving accuracy
|
|
There is still a danger of overflow if the results don't fit in
|
|
32 bits, though */
|
|
FxValue FxMul(FxValue a, FxValue b);
|
|
FxValue FxDiv(FxValue a, FxValue b);
|
|
int FxMulToInt(FxValue a, FxValue b);
|
|
FxValue FxMulDiv(FxValue a, FxValue m, FxValue d);
|
|
#endif
|
|
|
|
#ifndef FX_PRECISE_SQRT
|
|
FxValue FxSqrt(FxValue v);
|
|
/* Computing the square root of a demoted value leaves it out of
|
|
adjustment by sqrt(FX_MULT) so shift by FX_SHIFT/2 to
|
|
restore fixed point
|
|
FX_SHIFT should be even for this to work */
|
|
#define FxDemotedSqrt(v) (FxSqrt(FxDemote(v)) << (FX_SHIFT/2))
|
|
#else
|
|
#define FxSqrt(v) FxFltVal(sqrt(FxFlt(v)))
|
|
#define FxDemotedSqrt(v) FxSqrt(v)
|
|
#endif
|
|
|
|
#define FxDemotedMul(a, b) (FxDemote(a)*(b))
|
|
#define FxDemotedDiv(a, b) FxPromote((a)/(b))
|
|
#define FxDivToInt(a, b) ((int)((a)/(b)))
|
|
|
|
/* One unit of angle is the table quantum
|
|
One unit of angle equals 360/_fa_table_size degrees */
|
|
typedef FxValue FaAngle;
|
|
|
|
extern int _fa_table_size;
|
|
|
|
extern FxValue *_fa_sines;
|
|
extern FxValue *_fa_cosines;
|
|
|
|
#define FaAng(a) FxDemote(a)
|
|
#define FaSin(a) _fa_sines[(int)FaAng(a)]
|
|
#define FaCos(a) _fa_cosines[(int)FaAng(a)]
|
|
|
|
FaAngle FaAdd(FaAngle a, FaAngle d);
|
|
FaAngle FaBisectingAngle(FaAngle f, FaAngle t);
|
|
#define FaNorm(a) FaAdd(FxVal(0), a)
|
|
#define FaDeg(da) \
|
|
FaNorm(FxMulDiv(FxVal(da), _fa_table_size, 360))
|
|
#define FaRad(ra) FaNorm(FxFltVal((ra)*_fa_table_size/PI2))
|
|
#define FaAngVal(aa) FaNorm(FxVal(aa))
|
|
#define FaFltDegVal(ang) FxFltVal(FxMulDiv(ang, 360, _fa_table_size))
|
|
#define FaFltRadVal(ang) (FxFltVal(ang)*PI2/_fa_table_size)
|
|
|
|
BOOL FxInitialize(int table_size, ULONG flags);
|
|
void FxEnd(void);
|
|
|
|
#endif
|
|
|
|
typedef struct _FxPt2
|
|
{
|
|
FxValue x, y;
|
|
} FxPt2;
|
|
typedef FxPt2 FxVec2;
|
|
|
|
typedef struct _FxBox2
|
|
{
|
|
FxPt2 min, max;
|
|
} FxBox2;
|
|
|
|
typedef struct _FxPt3
|
|
{
|
|
FxValue x, y, z;
|
|
} FxPt3;
|
|
typedef FxPt3 FxVec3;
|
|
|
|
typedef struct _FxBox3
|
|
{
|
|
FxPt3 min, max;
|
|
} FxBox3;
|
|
|
|
typedef struct _FxPt4
|
|
{
|
|
FxValue x, y, z, w;
|
|
} FxPt4;
|
|
typedef FxPt4 FxVec4;
|
|
|
|
void FxBBox2Empty(FxBox2 *bb);
|
|
void FxBBox2AddPt(FxBox2 *bb, FxPt2 *pt);
|
|
|
|
void FxBBox3Empty(FxBox3 *bb);
|
|
void FxBBox3AddPt(FxBox3 *bb, FxPt3 *pt);
|
|
|
|
#define FxV2Set(v, xv, yv) \
|
|
((v)->x = (xv), (v)->y = (yv))
|
|
#define FxV2Add(a, b, r) \
|
|
((r)->x = (a)->x+(b)->x, (r)->y = (a)->y+(b)->y)
|
|
#define FxV2Sub(a, b, r) \
|
|
((r)->x = (a)->x-(b)->x, (r)->y = (a)->y-(b)->y)
|
|
#define FxV2Dot(a, b) \
|
|
(FxMul((a)->x, (b)->x)+FxMul((a)->y, (b)->y))
|
|
#define FxV2Neg(v, r) \
|
|
((r)->x = -(v)->x, (r)->y = -(v)->y)
|
|
#define FxV2NegV(v) FxV2Neg(v, v)
|
|
#define FxV2NormV(v) FxV2Norm(v, v)
|
|
|
|
FxValue FxV2Len(FxVec2 *v);
|
|
FxValue FxV2Norm(FxVec2 *v, FxVec2 *r);
|
|
|
|
#define FxvV2Set(v, xv, yv) FxV2Set(&(v), xv, yv)
|
|
#define FxvV2Add(a, b, r) FxV2Add(&(a), &(b), &(r))
|
|
#define FxvV2Sub(a, b, r) FxV2Sub(&(a), &(b), &(r))
|
|
#define FxvV2Dot(a, b) FxV2Dot(&(a), &(b))
|
|
#define FxvV2Neg(v, r) FxV2Neg(&(v), &(r))
|
|
#define FxvV2NegV(v) FxV2NegV(&(v))
|
|
#define FxvV2Len(v) FxV2Len(&(v))
|
|
#define FxvV2Norm(v, r) FxV2Norm(&(v), &(r))
|
|
#define FxvV2NormV(v) FxV2NormV(&(v))
|
|
|
|
#define FxV3Set(v, xv, yv, zv) \
|
|
((v)->x = (xv), (v)->y = (yv), (v)->z = (zv))
|
|
#define FxV3Add(a, b, r) \
|
|
((r)->x = (a)->x+(b)->x, (r)->y = (a)->y+(b)->y, (r)->z = (a)->z+(b)->z)
|
|
#define FxV3Sub(a, b, r) \
|
|
((r)->x = (a)->x-(b)->x, (r)->y = (a)->y-(b)->y, (r)->z = (a)->z-(b)->z)
|
|
#define FxV3Dot(a, b) \
|
|
(FxMul((a)->x, (b)->x)+FxMul((a)->y, (b)->y)+FxMul((a)->z, (b)->z))
|
|
#define FxV3Neg(v, r) \
|
|
((r)->x = -(v)->x, (r)->y = -(v)->y, (r)->z = -(v)->z)
|
|
#define FxV3NegV(v) FxV3Neg(v, v)
|
|
#define FxV3Cross(a, b, r) \
|
|
((r)->x = (a)->y*(b)->z-(b)->y*(a)->z,\
|
|
(r)->y = (a)->z*(b)->x-(b)->z*(a)->x,\
|
|
(r)->z = (a)->x*(b)->y-(b)->x*(a)->y)
|
|
#define FxV3NormV(v) FxV3Norm(v, v)
|
|
|
|
FxValue FxV3Len(FxVec3 *v);
|
|
FxValue FxV3Norm(FxVec3 *v, FxVec3 *r);
|
|
|
|
#define FxvV3Set(v, xv, yv, zv) FxV3Set(&(v), xv, yv, zv)
|
|
#define FxvV3Add(a, b, r) FxV3Add(&(a), &(b), &(r))
|
|
#define FxvV3Sub(a, b, r) FxV3Sub(&(a), &(b), &(r))
|
|
#define FxvV3Dot(a, b) FxV3Dot(&(a), &(b))
|
|
#define FxvV3Neg(v, r) FxV3Neg(&(v), &(r))
|
|
#define FxvV3NegV(v) FxV3NegV(&(v))
|
|
#define FxvV3Cross(a, b, r) FxV3Cross(&(a), &(b), &(r))
|
|
#define FxvV3Len(v) FxV3Len(&(v))
|
|
#define FxvV3Norm(v, r) FxV3Norm(&(v), &(r))
|
|
#define FxvV3NormV(v) FxV3NormV(&(v))
|
|
|
|
typedef FxValue FxMatrix2[2][2];
|
|
typedef FxValue FxMatrix3[3][3];
|
|
typedef FxValue FxMatrix4[4][4];
|
|
|
|
typedef FxValue FxTMatrix2[2][3];
|
|
typedef FxValue FxTMatrix3[3][4];
|
|
|
|
void FxT2Ident(FxTMatrix2 m);
|
|
void FxT2Mul(FxTMatrix2 a, FxTMatrix2 b, FxTMatrix2 r);
|
|
void FxT2Vec2(FxTMatrix2 m, int n, FxVec2 *f, FxVec2 *t);
|
|
|
|
void FxT3Ident(FxTMatrix3 m);
|
|
void FxT3Mul(FxTMatrix3 a, FxTMatrix3 b, FxTMatrix3 r);
|
|
void FxT3Vec3(FxTMatrix3 m, int n, FxVec3 *f, FxVec3 *t);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif
|