//===========================================================================// // File: scalar.hpp // // Contents: Base information used by all MUNGA source files // //---------------------------------------------------------------------------// // Copyright (C) Microsoft Corporation. All rights reserved. // //===========================================================================// #pragma once #include "Stuff.hpp" #include "MemoryStream.hpp" namespace Stuff { #if !defined(M_PI) #define M_PI 3.14159265358979323846 #endif typedef float Scalar; const Scalar Pi=static_cast(M_PI); const Scalar Pi_Over_2=static_cast(M_PI/2.0); const Scalar Pi_Over_3=static_cast(M_PI/3.0); const Scalar Pi_Over_4=static_cast(M_PI/4.0); const Scalar Pi_Over_6=static_cast(M_PI/6.0); const Scalar Pi_Over_8=static_cast(M_PI/8.0); const Scalar Two_Pi=static_cast(2.0*M_PI); const Scalar Degrees_Per_Radian=static_cast(180.0/M_PI); const Scalar Radians_Per_Degree=static_cast(M_PI/180.0); const int FP_ONE_BITS = 0x3F800000; inline Scalar Fabs(Scalar a) {return static_cast(fabs(a));} inline Scalar Lerp(Scalar a, Scalar b, Scalar t) {return a*(1.0f - t) + b*t;} inline bool Small_Enough(Scalar x,Scalar e=SMALL) {return Fabs(x) <= e;} inline bool Close_Enough(Scalar x,Scalar y,Scalar e=SMALL) {return Fabs(x-y) <= e;} inline bool Close_Enough(int x,int y,Scalar e=SMALL) {return Fabs(static_cast(x-y)) <= e;} inline WORD Round_Float_To_Word(float in) { Verify(in >= 0.0f && in < 65536.0f); in += 12582912.0f; return *Cast_Pointer(WORD*, &in); } inline BYTE Round_Float_To_Byte(float in) { Verify(in >= 0.0f && in < 256.0f); in += 12582912.0f; return *Cast_Pointer(BYTE*, &in); } inline WORD Truncate_Float_To_Word(float in) { Verify(in >= 0.0f && in < 65536.0f); in -= 0.5f; in += 12582912.0f; return *Cast_Pointer(WORD*, &in); } inline BYTE Truncate_Float_To_Byte(float in) { Verify(in >= 0.0f && in < 256.0f); in -= 0.5f; in += 12582912.0f; return *Cast_Pointer(BYTE*, &in); } DWORD Scaled_Float_To_Bits(float in, float min, float max, int bits); float Scaled_Float_From_Bits(DWORD in, float min, float max, int bits); DWORD Scaled_Int_To_Bits(int in, int min, int max, int bits); int Scaled_Int_From_Bits(DWORD in, int min, int max, int bits); int Round(Scalar value); // mg: I made some statistic test and came up with an max error of 6% static inline float SqrtApproximate(float f) { Verify(f >= 0.0f); #if USE_ASSEMBLER_CODE float temp; _asm { // __int32 i = (AsInt32(f) >> 1) + (INT32_FLOAT_ONE >> 1); mov eax, f sar eax, 1 add eax, 1FC00000h mov temp,eax } return temp; #else return static_castsqrt(f); #endif } static inline float OneOverApproximate(float f) { Verify(f != 0.0f); #if USE_ASSEMBLER_CODE float temp; int _i = 2 * FP_ONE_BITS - *(int *)&(f); temp = *(float *)&_i; temp = temp * (2.0f - (f) * temp); return temp; #else return 1.0f/f; #endif } void Find_Roots( Scalar a, // a*x*x + b*x + c = 0 Scalar b, Scalar c, Scalar *center, Scalar *range ); inline Scalar Sqrt(Scalar value) { Verify(value >= 0.0f); return static_cast(sqrt(value)); } inline Scalar Arctan( Scalar y, Scalar x ) { Verify(!Small_Enough(y) || !Small_Enough(x)); return static_cast(atan2(y,x)); } inline Scalar Arccos(Scalar x) { Verify(x>=-1.0f && x<=1.0f); return static_cast(acos(x)); } inline Scalar Arcsin(Scalar x) { Verify(x>=-1.0f && x<=1.0f); return static_cast(asin(x)); } inline Scalar Power( Scalar x, Scalar y ) { Verify(x >= 0); return static_cast( pow(static_cast(x), static_cast(y)) ); } inline Scalar Exp(Scalar v) { return static_cast(exp(v)); } inline Scalar Sin(Scalar v) { return static_cast(sin(v)); } inline Scalar Cos(Scalar v) { return static_cast(cos(v)); } inline Scalar Tan(Scalar v) { return static_cast(tan(v)); } inline Scalar AtoF(const char* v) { return static_cast(atof(v)); } typedef double Time; } namespace MemoryStreamIO { inline Stuff::MemoryStream& Read( Stuff::MemoryStream* stream, Stuff::Scalar *output ) {return stream->ReadBytes(output, sizeof(*output));} inline Stuff::MemoryStream& Write( Stuff::MemoryStream* stream, const Stuff::Scalar *input ) {return stream->WriteBytes(input, sizeof(*input));} }