Tiberian Technologies Scripts Reference Revision: 9000
Loading...
Searching...
No Matches
wwmath.h
1/* Renegade Scripts.dll
2 Copyright 2013 Tiberian Technologies
3
4 This file is part of the Renegade scripts.dll
5 The Renegade scripts.dll is free software; you can redistribute it and/or modify it under
6 the terms of the GNU General Public License as published by the Free
7 Software Foundation; either version 2, or (at your option) any later
8 version. See the file COPYING for more details.
9 In addition, an exemption is given to allow Run Time Dynamic Linking of this code with any closed source module that does not contain code covered by this licence.
10 Only the source code to the module(s) containing the licenced code has to be released.
11*/
12#ifndef TT__INCLUDE__WWMATH_H
13#define TT__INCLUDE__WWMATH_H
14#include <math.h>
15#include <float.h>
16#define WWMATH_EPSILON 0.0001f
17#define WWMATH_EPSILON2 WWMATH_EPSILON * WWMATH_EPSILON
18#define WWMATH_PI 3.141592654f
19#define WWMATH_FLOAT_MAX (FLT_MAX)
20#define WWMATH_FLOAT_MIN (FLT_MIN)
21#define WWMATH_FLOAT_TINY (1.0e-37f)
22#define WWMATH_SQRT2 1.414213562f
23#define WWMATH_SQRT3 1.732050808f
24#define WWMATH_OOSQRT2 0.707106781f
25#define WWMATH_OOSQRT3 0.577350269f
26#ifndef RAD_TO_DEG
27#define RAD_TO_DEG(x) (((double)x)*180.0/WWMATH_PI)
28#endif
29#ifndef DEG_TO_RAD
30#define DEG_TO_RAD(x) (((double)x)*WWMATH_PI/180.0)
31#endif
32#ifndef RAD_TO_DEGF
33#define RAD_TO_DEGF(x) (((float)x)*180.0f/WWMATH_PI)
34#endif
35#ifndef DEG_TO_RADF
36#define DEG_TO_RADF(x) (((float)x)*WWMATH_PI/180.0f)
37#endif
38const int ARC_TABLE_SIZE=1024;
39const int SIN_TABLE_SIZE=1024;
40#ifndef EXTERNAL
41SCRIPTS_API extern REF_ARR_DECL(float, _FastAcosTable, ARC_TABLE_SIZE);
42SCRIPTS_API extern REF_ARR_DECL(float, _FastAsinTable, ARC_TABLE_SIZE);
43SCRIPTS_API extern REF_ARR_DECL(float, _FastSinTable, SIN_TABLE_SIZE);
44SCRIPTS_API extern REF_ARR_DECL(float, _FastInvSinTable, SIN_TABLE_SIZE);
45#else
46extern float _FastAcosTable[ARC_TABLE_SIZE];
47extern float _FastAsinTable[ARC_TABLE_SIZE];
48extern float _FastSinTable[SIN_TABLE_SIZE];
49extern float _FastInvSinTable[SIN_TABLE_SIZE];
50#endif
51class SCRIPTS_API WWMath
52{
53public:
54 static void Init(void);
55 static void Shutdown(void);
56 static TT_INLINE float Fabs(float val)
57 {
58 int value=*(int*)&val;
59 value&=0x7fffffff;
60 return *(float*)&value;
61 }
62 static TT_INLINE int Float_To_Int_Chop(const float& f);
63 static TT_INLINE int Float_To_Int_Floor(const float& f);
64 static TT_INLINE float Cos(float val);
65 static TT_INLINE float Sin(float val);
66 static TT_INLINE float Sqrt(float val);
67 static float __fastcall Inv_Sqrt(float a);
68 static TT_INLINE long Float_To_Long(float f);
69 static TT_INLINE float Fast_Sin(float val);
70 static TT_INLINE float Fast_Inv_Sin(float val);
71 static TT_INLINE float Fast_Cos(float val);
72 static TT_INLINE float Fast_Inv_Cos(float val);
73 static TT_INLINE float Fast_Acos(float val);
74 static TT_INLINE float Fast_Asin(float val);
75 static TT_INLINE float Acos(float val);
76 static TT_INLINE float Asin(float val);
77 static float Atan(float x) { return static_cast<float>(atan(x)); }
78 static float Atan2(float y,float x) { return static_cast<float>(atan2(y,x)); }
79 static float Sign(float val);
80 static float Ceil(float val) { return ceilf(val); }
81 static float Floor(float val) { return floorf(val); }
82 static bool Fast_Is_Float_Positive(const float & val);
83 static float Random_Float(void);
84 static float Random_Float(float min,float max);
85 static float Clamp(float val, float min = 0.0f, float max = 1.0f);
86 static double Clamp(double val, double min = 0.0f, double max = 1.0f);
87 static int Clamp_Int(int val, int min_val, int max_val);
88 static float Wrap(float val, float min = 0.0f, float max = 1.0f);
89 static double Wrap(double val, double min = 0.0f, double max = 1.0f);
90 static float Min(float a, float b);
91 static float Max(float a, float b);
92 static float Lerp(float a, float b, float lerp );
93 static double Lerp(double a, double b, float lerp );
94 static int Lerp(int a, int b, float lerp );
95 static long Float_To_Long(double f);
96 static unsigned char Unit_Float_To_Byte(float f) { return (unsigned char)(f*255.0f); }
97 static float Byte_To_Unit_Float(unsigned char byte) { return ((float)byte) / 255.0f; }
98 static bool Is_Valid_Float(float x);
99 static bool Is_Valid_Double(double x);
100};
101TT_INLINE float WWMath::Sign(float val)
102{
103 if (val > 0.0f) {
104 return +1.0f;
105 }
106 if (val < 0.0f) {
107 return -1.0f;
108 }
109 return 0.0f;
110}
111
112TT_INLINE bool WWMath::Fast_Is_Float_Positive(const float & val)
113{
114 return !((*(int *)(&val)) & 0x80000000);
115}
116
117TT_INLINE float WWMath::Random_Float(float min,float max)
118{
119 return Random_Float() * (max-min) + min;
120}
121
122TT_INLINE float WWMath::Clamp(float val, float min, float max)
123{
124 if(val < min) return min;
125 if(val > max) return max;
126 return val;
127}
128
129TT_INLINE double WWMath::Clamp(double val, double min, double max)
130{
131 if(val < min) return min;
132 if(val > max) return max;
133 return val;
134}
135
136TT_INLINE int WWMath::Clamp_Int(int val, int min_val, int max_val)
137{
138 if(val < min_val) return min_val;
139 if(val > max_val) return max_val;
140 return val;
141}
142
143TT_INLINE float WWMath::Wrap(float val, float min, float max)
144{
145 if ( val >= max ) val -= (max-min);
146 if ( val < min ) val += (max-min);
147 if ( val < min ) {
148 val = min;
149 }
150 if ( val > max ) {
151 val = max;
152 }
153 return val;
154}
155
156TT_INLINE double WWMath::Wrap(double val, double min, double max)
157{
158 if ( val >= max ) val -= (max-min);
159 if ( val < min ) val += (max-min);
160 if ( val < min ) {
161 val = min;
162 }
163 if ( val > max ) {
164 val = max;
165 }
166 return val;
167}
168
169TT_INLINE float WWMath::Min(float a, float b)
170{
171 if (a<b) return a;
172 return b;
173}
174
175TT_INLINE float WWMath::Max(float a, float b)
176{
177 if (a>b) return a;
178 return b;
179}
180
181TT_INLINE float WWMath::Lerp(float a, float b, float lerp )
182{
183 return (a + (b - a)*lerp);
184}
185
186TT_INLINE double WWMath::Lerp(double a, double b, float lerp )
187{
188 return (a + (b - a)*lerp);
189}
190
191TT_INLINE int WWMath::Lerp(int a, int b, float lerp )
192{
193 return (a + (int)((b - a)*lerp));
194}
195
196TT_INLINE bool WWMath::Is_Valid_Float(float x)
197{
198 unsigned long * plong = (unsigned long *)(&x);
199 unsigned long exponent = ((*plong) & 0x7F800000) >> (32-9);
200 if (exponent == 0xFF) {
201 return false;
202 }
203 return true;
204}
205
206TT_INLINE bool WWMath::Is_Valid_Double(double x)
207{
208 unsigned long * plong = (unsigned long *)(&x) + 1;
209 unsigned long exponent = ((*plong) & 0x7FF00000) >> (32-12);
210 if (exponent == 0x7FF) {
211 return false;
212 }
213 return true;
214}
215
216TT_INLINE long WWMath::Float_To_Long(float f)
217{
218 return _mm_cvtt_ss2si(_mm_load_ss(&f));
219}
220
221TT_INLINE long WWMath::Float_To_Long(double f)
222{
223 return _mm_cvttsd_si32(_mm_load_pd(&f));
224}
225
226TT_INLINE float WWMath::Cos(float val)
227{
228 return ::cos(val);
229}
230
231TT_INLINE float WWMath::Sin(float val)
232{
233 return ::sin(val);
234}
235
236TT_INLINE float WWMath::Fast_Sin(float val)
237{
238 val*=float(SIN_TABLE_SIZE) / (2.0f * WWMATH_PI);
239 int idx0=Float_To_Int_Floor(val);
240 int idx1=idx0+1;
241 float frac=val-(float)idx0;
242 idx0 = ((unsigned)idx0) & (SIN_TABLE_SIZE-1);
243 idx1 = ((unsigned)idx1) & (SIN_TABLE_SIZE-1);
244 return (1.0f - frac) * _FastSinTable[idx0] + frac * _FastSinTable[idx1];
245}
246
247TT_INLINE float WWMath::Fast_Inv_Sin(float val)
248{
249 return 1.0f / WWMath::Fast_Sin(val);
250}
251
252TT_INLINE float WWMath::Fast_Cos(float val)
253{
254 val+=(WWMATH_PI * 0.5f);
255 val*=float(SIN_TABLE_SIZE) / (2.0f * WWMATH_PI);
256 int idx0=Float_To_Int_Floor(val);
257 int idx1=idx0+1;
258 float frac=val-(float)idx0;
259 idx0 = ((unsigned)idx0) & (SIN_TABLE_SIZE-1);
260 idx1 = ((unsigned)idx1) & (SIN_TABLE_SIZE-1);
261 return (1.0f - frac) * _FastSinTable[idx0] + frac * _FastSinTable[idx1];
262}
263
264TT_INLINE float WWMath::Fast_Inv_Cos(float val)
265{
266 return 1.0f / WWMath::Fast_Cos(val);
267}
268
269TT_INLINE float WWMath::Fast_Acos(float val)
270{
271 if (WWMath::Fabs(val) > 0.975f) {
272 return WWMath::Acos(val);
273 }
274 val*=float(ARC_TABLE_SIZE/2);
275 int idx0=Float_To_Int_Floor(val);
276 int idx1=idx0+1;
277 float frac=val-(float)idx0;
278 idx0+=ARC_TABLE_SIZE/2;
279 idx1+=ARC_TABLE_SIZE/2;
280 TT_ASSERT((idx0 >= 0) && (idx0 < ARC_TABLE_SIZE));
281 TT_ASSERT((idx1 >= 0) && (idx1 < ARC_TABLE_SIZE));
282 return (1.0f - frac) * _FastAcosTable[idx0] + frac * _FastAcosTable[idx1];
283}
284
285TT_INLINE float WWMath::Acos(float val)
286{
287 return (float)acos(val);
288}
289
290TT_INLINE float WWMath::Fast_Asin(float val)
291{
292 if (WWMath::Fabs(val) > 0.975f) {
293 return WWMath::Asin(val);
294 }
295 val*=float(ARC_TABLE_SIZE/2);
296 int idx0=Float_To_Int_Floor(val);
297 int idx1=idx0+1;
298 float frac=val-(float)idx0;
299 idx0+=ARC_TABLE_SIZE/2;
300 idx1+=ARC_TABLE_SIZE/2;
301 TT_ASSERT((idx0 >= 0) && (idx0 < ARC_TABLE_SIZE));
302 TT_ASSERT((idx1 >= 0) && (idx1 < ARC_TABLE_SIZE));
303 return (1.0f - frac) * _FastAsinTable[idx0] + frac * _FastAsinTable[idx1];
304}
305TT_INLINE float WWMath::Asin(float val)
306{
307 return (float)asin(val);
308}
309
310TT_INLINE float WWMath::Sqrt(float val)
311{
312 return ::sqrtf(val);
313}
314
315TT_INLINE int WWMath::Float_To_Int_Chop(const float& f)
316{
317 int a = *reinterpret_cast<const int*>(&f);
318 int sign = (a>>31);
319 int mantissa = (a&((1<<23)-1))|(1<<23);
320 int exponent = ((a&0x7fffffff)>>23)-127;
321 int r = ((unsigned int)(mantissa)<<8)>>(31-exponent);
322 return ((r ^ (sign)) - sign ) &~ (exponent>>31);
323}
324
325TT_INLINE int WWMath::Float_To_Int_Floor (const float& f)
326{
327 int a = *reinterpret_cast<const int*>(&f);
328 int sign = (a>>31);
329 a&=0x7fffffff;
330 int exponent = (a>>23)-127;
331 int expsign = ~(exponent>>31);
332 int imask = ( (1<<(31-(exponent))))-1;
333 int mantissa = (a&((1<<23)-1));
334 int r = ((unsigned int)(mantissa|(1<<23))<<8)>>(31-exponent);
335#pragma warning(suppress: 6290) //warning C6290: Bitwise operation on logical result: ! has higher precedence than &. Use && or (!(x & y)) instead
336 r = ((r & expsign) ^ (sign)) + ((!((mantissa<<8)&imask)&(expsign^((a-1)>>31)))&sign);
337 return r;
338}
339
340inline float WWMath::Inv_Sqrt(float number)
341{
342 return 1.f / sqrt(number);
343}
344
345#endif