File: myMath.h

package info (click to toggle)
spring 0.81.2.1%2Bdfsg1-6
  • links: PTS, VCS
  • area: main
  • in suites: squeeze
  • size: 28,496 kB
  • ctags: 37,096
  • sloc: cpp: 238,659; ansic: 13,784; java: 12,175; awk: 3,428; python: 1,159; xml: 738; perl: 405; sh: 297; makefile: 267; pascal: 228; objc: 192
file content (257 lines) | stat: -rw-r--r-- 5,739 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
#ifndef MYMATH_H
#define MYMATH_H

#include "Sim/Misc/GlobalConstants.h"
#include "Vec2.h"
#include "float3.h"

#define MaxByAbs(a,b) (abs((a)) > abs((b))) ? (a) : (b);

static const float TWOPI = 2*PI;

#define SHORTINT_MAXVALUE 32768

#define HEADING_CHECKSUM_1024 0x617a9968
#define HEADING_CHECKSUM_4096 0x3d51b476
#define NUM_HEADINGS 4096

#if (NUM_HEADINGS == 1024)
#  define HEADING_CHECKSUM  HEADING_CHECKSUM_1024
#elif (NUM_HEADINGS == 4096)
#  define HEADING_CHECKSUM  HEADING_CHECKSUM_4096
#else
#  error "HEADING_CHECKSUM not set, invalid NUM_HEADINGS?"
#endif

enum FacingMap {
	FACING_NORTH = 2,
	FACING_SOUTH = 0,
	FACING_EAST  = 1,
	FACING_WEST  = 3
};

class CMyMath {
public:
	static void Init();
	static float2 headingToVectorTable[NUM_HEADINGS];
};



//                  F(N=2) = H(-32768 / 32767)
// 
//                         ^
//                         |
//                         |
// F(W=3) = H(-16384)  <---o--->  F(E=1) = H(16384)
//                         |
//                         |
//                         v
// 
//                  F(S=0) = H(0)
inline short int GetHeadingFromFacing(int facing)
{
	switch (facing) {
		case FACING_SOUTH: return      0;
		case FACING_EAST:  return  16384;
		case FACING_NORTH: return  32767;
		case FACING_WEST:  return -16384;
		default: return 0;
	}
}

inline int GetFacingFromHeading(short int heading)
{
	if (heading >= 0) {
		if (heading <  8192) { return FACING_SOUTH; }
		if (heading < 24576) { return FACING_EAST; }
		return FACING_NORTH;
	} else {
		if (heading >=  -8192) { return FACING_SOUTH; }
		if (heading >= -24576) { return FACING_WEST; }
		return FACING_NORTH;
	}
}

inline float GetHeadingFromVectorF(float dx, float dz)
{
	float h = 0.0f;

	if (dz != 0.0f) {
		float d = dx / dz;

		if (d > 1.0f) {
			h = (PI * 0.5f) - d / (d * d + 0.28f);
		} else if (d < -1.0f) {
			h = -(PI * 0.5f) - d / (d * d + 0.28f);
		} else {
			h = d / (1.0f + 0.28f * d * d);
		}

		if (dz < 0.0f) {
			if (dx > 0.0f)
				h += PI;
			else
				h -= PI;
		}
	} else {
		if (dx > 0.0f)
			h = PI * 0.5f;
		else
			h = -PI * 0.5f;
	}

	return h;
}

inline short int GetHeadingFromVector(float dx, float dz)
{
	float h = GetHeadingFromVectorF(dx, dz);

	h *= SHORTINT_MAXVALUE / PI;

	// Prevents h from going beyond SHORTINT_MAXVALUE.
	// If h goes beyond SHORTINT_MAXVALUE, the following
	// conversion to a short int crashes.
	// if (h > SHORTINT_MAXVALUE) h = SHORTINT_MAXVALUE;
	// return (short int) h;

	int ih = (int) h;
	if (ih == -SHORTINT_MAXVALUE) {
		// ih now represents due-north, but the modulo operation
		// below would cause it to wrap around from -32768 to 0
		// which means due-south, so add 1
		ih += 1;
	}
	ih %= SHORTINT_MAXVALUE;
	return (short int) ih;
}

struct shortint2 {
	short int x, y;
};

// vec should be normalized
inline shortint2 GetHAndPFromVector(const float3& vec)
{
	shortint2 ret;

	// Prevents ret.y from going beyond SHORTINT_MAXVALUE.
	// If h goes beyond SHORTINT_MAXVALUE, the following
	// conversion to a short int crashes.
	// this change destroys the whole meaning with using short ints....
	#if defined BUILDING_AI
	int iy = (int) (std::asin(vec.y) * (SHORTINT_MAXVALUE / PI));
	#else
	int iy = (int) (streflop::asin(vec.y) * (SHORTINT_MAXVALUE / PI));
	#endif // defined BUILDING_AI
	iy %= SHORTINT_MAXVALUE;
	ret.y = (short int) iy;
	ret.x = GetHeadingFromVector(vec.x, vec.z);
	return ret;
}

// vec should be normalized
inline float2 GetHAndPFromVectorF(const float3& vec)
{
	float2 ret;

	#if defined BUILDING_AI
	ret.y = std::asin(vec.y);
	#else
	ret.y = streflop::asin(vec.y);
	#endif // defined BUILDING_AI
	ret.x = GetHeadingFromVectorF(vec.x, vec.z);
	return ret;
}

inline float3 GetVectorFromHeading(short int heading)
{
	float2 v = CMyMath::headingToVectorTable[heading / ((SHORTINT_MAXVALUE/NUM_HEADINGS) * 2) + NUM_HEADINGS/2];
	return float3(v.x, 0.0f, v.y);
}

float3 GetVectorFromHAndPExact(short int heading,short int pitch);

inline float3 CalcBeizer(float i, const float3& p1, const float3& p2, const float3& p3, const float3& p4)
{
	float ni = 1 - i;

	float3 res((p1 * ni * ni * ni) + (p2 * 3 * i * ni * ni) + (p3 * 3 * i * i * ni) + (p4 * i * i * i));
	return res;
}

float LinePointDist(const float3& l1, const float3& l2, const float3& p);
float3 ClosestPointOnLine(const float3& l1, const float3& l2, const float3& p);


#ifndef __GNUC__
float Square(const float x);
#else
float Square(const float x) __attribute__((const));
#endif

inline float Square(const float x) { return x * x; }

float smoothstep(const float edge0, const float edge1, const float value);
float3 smoothstep(const float edge0, const float edge1, float3 vec);


inline float Clamp(const float& v, const float& min, const float& max)
{
	if (v>max) {
		return max;
	} else if (v<min) {
		return min;
	}
	return v;
}

/**
 * @brief Clamps an radian angle between 0 .. 2*pi
 * @param f float* value to clamp
 */
#ifndef __GNUC__
float ClampRad(float f);
#else
float ClampRad(float f) __attribute__((const));
#endif

inline float ClampRad(float f)
{
	f = fmod(f, TWOPI);
	if (f < 0.0f) f += TWOPI;
	return f;
}



/**
 * @brief Clamps an radian angle between 0 .. 2*pi
 * @param f float* value to clamp
 */
inline void ClampRad(float* f)
{
	*f = fmod(*f, TWOPI);
	if (*f < 0.0f) *f += TWOPI;
}



/**
 * @brief Checks if 2 radian values discribe the same angle
 * @param f1 float* first compare value
 * @param f2 float* second compare value
 */
#ifndef __GNUC__
bool RadsAreEqual(const float f1, const float f2);
#else
bool RadsAreEqual(const float f1, const float f2) __attribute__((const));
#endif

inline bool RadsAreEqual(const float f1, const float f2)
{
	return (fmod(f1 - f2, TWOPI) == 0.0f);
}

#endif // MYMATH_H