#ifndef __FIXED_H__ #define __FIXED_H__ #include #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