1 /////////////////////////////////////////
2 //
3 //   OpenLieroX
4 //
5 //   Auxiliary Software class library
6 //
7 //   based on the work of JasonB
8 //   enhanced by Dark Charlie and Albert Zeyer
9 //
10 //   code under LGPL
11 //
12 /////////////////////////////////////////
13 
14 
15 // Mathematics Library
16 // Created 20/12/01
17 // Jason Boettcher
18 
19 
20 #include <cassert>
21 #include <stdlib.h>
22 #include <cmath>
23 #include <time.h>
24 #include <SDL_timer.h>
25 
26 #include "MathLib.h"
27 
28 
29 const int HALF_RAND = (RAND_MAX / 2);
30 
31 
32 //////////////////////////////////////
33 //				Generic maths
34 //////////////////////////////////////
35 
36 
37 ///////////////////
38 // Faster SQRT function
fastSQRT(float x)39 float fastSQRT(float x)
40 {
41 
42     /*if(x <= 0) return 0;
43 
44 	float tmp = x / 2;
45 	for(short i = 0; i<=10; i++) {
46 		tmp = tmp + x / tmp;
47 		tmp = tmp / 2;
48 	}
49 	return tmp;*/
50 
51 
52 	return (float)sqrt(x);
53 }
54 
55 
56 ///////////////////
57 // Get a random number between -1 and 1
GetRandomNum()58 float GetRandomNum()
59 {
60 	int rn = rand();
61 	return ((float)(rn - HALF_RAND) / (float)HALF_RAND);
62 }
63 
GetRandomPosNum()64 float GetRandomPosNum() {
65 	int rn = rand();
66 	return (float)rn / (float)RAND_MAX;
67 }
68 
69 ///////////////////
70 // Get a random integer with a max value
GetRandomInt(int max)71 int GetRandomInt(int max)
72 {
73 	assert(max >= 0);
74 	float f = GetRandomPosNum()*(float)(max+1);
75 	return CLAMP((int)f, 0, max);
76 }
77 
78 //////////////////
79 // Round the number
Round(float x)80 int Round(float x)
81 {
82         return (int) ceil((double)x-0.5);
83 }
84 
85 
86 //#ifdef VEC2D
87 
88 //////////////////////////////////////
89 //				2D Section
90 //////////////////////////////////////
91 
92 
93 ///////////////////
94 // Calculate the distance between 2 vectors
CalculateDistance(CVec p1,CVec p2)95 float CalculateDistance(CVec p1, CVec p2)
96 {
97 	CVec dist = p2-p1;
98 	return fastSQRT( (dist.x*dist.x) + (dist.y*dist.y) );
99 }
100 
101 
102 ///////////////////
103 // Normalize a vector
NormalizeVector(CVec * vec)104 float NormalizeVector(CVec *vec)
105 {
106 	float length;
107 
108 	length = (float)fastSQRT( vec->x*vec->x + vec->y*vec->y );
109 
110 	if(length) {
111 		vec->x /= length;
112 		vec->y /= length;
113 	}
114 
115 	return length;
116 }
117 
118 
119 ///////////////////
120 // Get a random normalized vector
GetRandomVec()121 CVec GetRandomVec()
122 {
123 	return CVec(GetRandomNum(),GetRandomNum());
124 }
125 
126 
127 ///////////////////
128 // Get forward, and right vectors from a yaw angle
GetVecsFromAngle(float yaw,CVec * forward,CVec * right)129 void GetVecsFromAngle(float yaw,CVec *forward, CVec *right)
130 {
131 	const float angle = yaw * (float)(PI / 180);
132 	const float sy = sinf(angle);
133 	const float cy = cosf(angle);
134 	const float sp = 0; //sinf(0);
135 	const float cp = 1; //cosf(0);
136 	const float sr = sp;
137 	const float cr = cp;
138 
139 	if(forward)
140 		*forward = CVec(cp*cy,cp*sy);
141 	if(right)
142 		*right = CVec((-1*sr*sp*cy+-1*cr*-sy),(-1*sr*sp*sy+-1*cr*cy));
143 }
144 
GetVecFromAngle(float yaw)145 CVec GetVecFromAngle(float yaw) {
146 	CVec ret;
147 	GetVecsFromAngle(yaw, &ret, NULL);
148 	return ret;
149 }
150 
151 
152 //////////////////
153 // Get the angle (in radians) of two vectors
VectorAngle(CVec vec1,CVec vec2)154 float VectorAngle(CVec vec1, CVec vec2)
155 {
156 	return (float)atan2(vec1.y-vec2.y,vec1.x-vec2.x);
157 
158 /*	//return (float)acos(vec1.x*vec2.x+vec1.y*vec2.y)/(VectorLength(vec1)*VectorLength(vec2));
159 	float scalar = vec1.x*vec2.x + vec1.y*vec2.y;
160 	float len1 = vec1.GetLength();
161 	float len2 = vec2.GetLength();
162 	float result = (float)acos(scalar/(len1*len2));
163 	return result; */
164 }
165 
166 
167 ///////////////////
168 // Get the length of a vector
VectorLength(CVec vec)169 float VectorLength(CVec vec)
170 {
171 	return (float)fastSQRT( vec.x*vec.x + vec.y*vec.y );
172 }
173 
174 ////////////////////
175 // Create a parabola from three points
Parabola(CVec p1,CVec p2,CVec p3)176 Parabola::Parabola(CVec p1, CVec p2, CVec p3)
177 {
178 	const float m = p1.x;
179 	const float n = p1.y;
180 	const float o = p2.x;
181 	const float p = p2.y;
182 	const float q = p3.x;
183 	const float r = p3.y;
184 
185 	const float denom = (pow(m,2)-m*(o+q)+o*q)*(o-q);
186 	if (denom == 0)  {
187 		a = b = c = 0;
188 		return;
189 	}
190 
191 	a = -(m*(p-r)+n*(q-o)+o*r-p*q)/denom;
192 	b = (m*m*(p-r)+n*(o+q)*(q-o)+o*o*r-p*q*q)/denom;
193 	c = (m*m*(o*r-p*q)+m*(p*q*q-o*o*r)+n*o*q*(o-q))/denom;
194 }
195 
196 /////////////////////
197 // Create a parabola from two points and a tangent angle in point p1
Parabola(CVec p1,float angleP1,CVec p2)198 Parabola::Parabola(CVec p1, float angleP1, CVec p2)
199 {
200 	const float p = p1.x;
201 	const float r = p1.y;
202 	const float s = p2.x;
203 	const float t = p2.y;
204 	const float cos_f = cosf(angleP1);
205 	const float sin_f = sinf(angleP1);
206 
207 	const float denom = (p-s) * (p-s) * cos_f;
208 	if (denom == 0)  {
209 		a = b = c = 0;
210 		return;
211 	}
212 
213 	a = -((r-t)*cos_f+(s-p)*sin_f)/denom;
214 	b = (2*p*(r-t)*cos_f+(p+s)*(s-p)*sin_f)/denom;
215 	c = ((p*p*t-2*p*r*s+r*s*s)*cos_f+p*s*(p-s)*sin_f)/denom;
216 }
217 
218 /////////////////////
219 // Get length of a parabola segment between points p1 and p2, p1 and p2 must be part of the parabola
getLength(CVec p1,CVec p2)220 float Parabola::getLength(CVec p1, CVec p2)
221 {
222 	if (isPointAtParabola(p1) && isPointAtParabola(p2))
223 		return getLength(p1.x, p2.x);
224 	else
225 		return -1;
226 }
227 
getLength(float pa,float pb)228 float Parabola::getLength(float pa, float pb)
229 {
230 	// Check if we have a line
231 	if (a == 0)  {
232 		CVec x1(pa, b * pa + c);
233 		CVec x2(pb, b * pb + c);
234 		return (x2 - x1).GetLength();
235 	}
236 
237 	float upper_u = 2*a*pa + b;
238 	float lower_u = 2*a*pb + b;
239 
240 	float up = (log(sqrt(upper_u*upper_u + 1) + upper_u) + upper_u*sqrt(upper_u*upper_u + 1))/(4*a);
241 	float low = (log(sqrt(lower_u*lower_u + 1) + lower_u) + lower_u*sqrt(lower_u*lower_u + 1))/(4*a);
242 
243 	return fabs(up - low);
244 }
245