Line data Source code
1 0 : /*
2 :
3 : OOVector.h
4 :
5 : Mathematical framework for Oolite.
6 :
7 : Oolite
8 : Copyright (C) 2004-2013 Giles C Williams and contributors
9 :
10 : This program is free software; you can redistribute it and/or
11 : modify it under the terms of the GNU General Public License
12 : as published by the Free Software Foundation; either version 2
13 : of the License, or (at your option) any later version.
14 :
15 : This program is distributed in the hope that it will be useful,
16 : but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : GNU General Public License for more details.
19 :
20 : You should have received a copy of the GNU General Public License
21 : along with this program; if not, write to the Free Software
22 : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
23 : MA 02110-1301, USA.
24 :
25 : */
26 :
27 :
28 : #ifndef INCLUDED_OOMATHS_h
29 : #error Do not include OOVector.h directly; include OOMaths.h.
30 : #else
31 :
32 :
33 : #ifndef OOMATHS_EXTERNAL_VECTOR_TYPES
34 :
35 : typedef struct Vector
36 : {
37 : OOScalar x;
38 : OOScalar y;
39 : OOScalar z;
40 : } Vector;
41 :
42 :
43 : typedef struct Vector2D
44 : {
45 : OOScalar x;
46 : OOScalar y;
47 : } Vector2D;
48 :
49 : #endif
50 :
51 :
52 : extern const Vector kZeroVector, /* 0, 0, 0 */
53 : kBasisXVector, /* 1, 0, 0 */
54 : kBasisYVector, /* 0, 1, 0 */
55 : kBasisZVector; /* 0, 0, 1 */
56 :
57 :
58 : extern const Vector2D kZeroVector2D, /* 0, 0 */
59 : kBasisXVector2D, /* 1, 0 */
60 : kBasisYVector2D; /* 0, 1 */
61 :
62 :
63 : /* Construct vector */
64 : OOINLINE Vector make_vector(OOScalar vx, OOScalar vy, OOScalar vz) INLINE_CONST_FUNC;
65 : OOINLINE Vector2D MakeVector2D(OOScalar vx, OOScalar vy) INLINE_CONST_FUNC;
66 :
67 : #if !OOMATHS_STANDALONE
68 : /* Generate random vectors. */
69 : Vector OORandomUnitVector(void);
70 : Vector OOVectorRandomSpatial(OOScalar maxLength); // Random vector uniformly distributed in radius-maxLength sphere. (Longer vectors are more common.)
71 : Vector OOVectorRandomRadial(OOScalar maxLength); // Random vector with uniform distribution of direction and radius in radius-maxLength sphere. (Causes clustering at centre.)
72 : // only needed in high-precision forms so far
73 : //Vector OORandomPositionInCylinder(Vector centre1, OOScalar exclusion1, Vector centre2, OOScalar exclusion2, OOScalar radius);
74 : //Vector OORandomPositionInShell(Vector centre, OOScalar inner, OOScalar outer);
75 : #endif
76 :
77 : /* Multiply vector by scalar (in place) */
78 : OOINLINE void scale_vector(Vector *outVector, OOScalar factor) ALWAYS_INLINE_FUNC NONNULL_FUNC;
79 :
80 : /* Multiply vector by scalar */
81 : OOINLINE Vector vector_multiply_scalar(Vector v, OOScalar s) INLINE_CONST_FUNC;
82 :
83 : /* Addition and subtraction of vectors */
84 : OOINLINE Vector vector_add(Vector a, Vector b) INLINE_CONST_FUNC;
85 : OOINLINE Vector vector_subtract(Vector a, Vector b) INLINE_CONST_FUNC;
86 : #define vector_between(a, b) vector_subtract(b, a)
87 : OOINLINE Vector vector_flip(Vector v) INLINE_CONST_FUNC;
88 :
89 : /* Vector linear interpolation */
90 : OOINLINE Vector OOVectorInterpolate(Vector a, Vector b, OOScalar where) INLINE_CONST_FUNC;
91 : OOINLINE Vector OOVectorTowards(Vector a, Vector b, OOScalar where) INLINE_CONST_FUNC;
92 :
93 : /* Comparison of vectors */
94 : OOINLINE bool vector_equal(Vector a, Vector b) INLINE_CONST_FUNC;
95 :
96 : /* Square of magnitude of vector */
97 : OOINLINE OOScalar magnitude2(Vector vec) INLINE_CONST_FUNC;
98 :
99 : /* Magnitude of vector */
100 : OOINLINE OOScalar magnitude(Vector vec) INLINE_CONST_FUNC;
101 :
102 : /* Normalize vector */
103 : OOINLINE Vector vector_normal(Vector vec) INLINE_CONST_FUNC;
104 :
105 : /* Normalize vector, returning fallback if zero vector. */
106 : OOINLINE Vector vector_normal_or_fallback(Vector vec, Vector fallback) INLINE_CONST_FUNC;
107 : OOINLINE Vector vector_normal_or_xbasis(Vector vec) INLINE_CONST_FUNC;
108 : OOINLINE Vector vector_normal_or_ybasis(Vector vec) INLINE_CONST_FUNC;
109 : OOINLINE Vector vector_normal_or_zbasis(Vector vec) INLINE_CONST_FUNC;
110 :
111 : /* Square of distance between vectors */
112 : OOINLINE OOScalar distance2(Vector v1, Vector v2) INLINE_CONST_FUNC;
113 :
114 : /* Distance between vectors */
115 : OOINLINE OOScalar distance(Vector v1, Vector v2) INLINE_CONST_FUNC;
116 :
117 : /* Dot product */
118 : OOINLINE OOScalar dot_product (Vector first, Vector second) INLINE_CONST_FUNC;
119 :
120 : /* NORMALIZED cross product */
121 : OOINLINE Vector cross_product(Vector first, Vector second) INLINE_CONST_FUNC;
122 :
123 : /* General cross product */
124 : OOINLINE Vector true_cross_product(Vector first, Vector second) CONST_FUNC;
125 :
126 : /* Triple product */
127 : OOINLINE OOScalar triple_product(Vector first, Vector second, Vector third) INLINE_CONST_FUNC;
128 :
129 : /* Given three points on a surface, returns the normal to the surface. */
130 : OOINLINE Vector normal_to_surface(Vector v1, Vector v2, Vector v3) CONST_FUNC;
131 :
132 : #if __OBJC__
133 : NSString *VectorDescription(Vector vector); // @"(x, y, z)"
134 :
135 : /* For storing vectors in NSArrays */
136 : @interface OONativeVector: NSObject
137 : {
138 : @private
139 : Vector v;
140 : }
141 : - (id) initWithVector:(Vector)vect;
142 : - (Vector) getVector;
143 :
144 : @end
145 :
146 : #endif
147 :
148 : #if OOMATHS_OPENGL_INTEGRATION
149 : /* OpenGL conveniences. Need to be macros to work with OOMacroOpenGL. */
150 : #define GLVertexOOVector(v) do { Vector v_ = v; glVertex3f(v_.x, v_.y, v_.z); } while (0)
151 : #define GLTranslateOOVector(v) do { Vector v_ = v; OOGL(glTranslatef(v_.x, v_.y, v_.z)); } while (0)
152 : #endif
153 :
154 :
155 : /*** Only inline definitions beyond this point ***/
156 :
157 : OOINLINE Vector make_vector (OOScalar vx, OOScalar vy, OOScalar vz)
158 : {
159 : Vector result;
160 : result.x = vx;
161 : result.y = vy;
162 : result.z = vz;
163 : return result;
164 : }
165 :
166 :
167 : OOINLINE Vector2D MakeVector2D(OOScalar vx, OOScalar vy)
168 : {
169 : Vector2D result;
170 : result.x = vx;
171 : result.y = vy;
172 : return result;
173 : }
174 :
175 :
176 : OOINLINE void scale_vector(Vector *vec, OOScalar factor)
177 : {
178 : /*
179 : Clang static analyzer: reports an unintialized value here when called
180 : from -[HeadUpDisplay rescaleByFactor:]. This is blatantly wrong, as
181 : the array the vector comes from is fully initialized in the range being
182 : looped over.
183 : -- Ahruman 2012-09-14
184 : */
185 : vec->x *= factor;
186 : vec->y *= factor;
187 : vec->z *= factor;
188 : }
189 :
190 :
191 : OOINLINE Vector vector_multiply_scalar(Vector v, OOScalar s)
192 : {
193 : /*
194 : Clang static analyzer: reports a garbage value here when called from
195 : -[OOMesh rescaleByFactor:], apparently on baseless assumption that
196 : OOMesh._vertices points to only one vertex.
197 : -- Ahruman 2012-09-14
198 : */
199 : Vector r;
200 : r.x = v.x * s;
201 : r.y = v.y * s;
202 : r.z = v.z * s;
203 : return r;
204 : }
205 :
206 :
207 : OOINLINE Vector vector_add(Vector a, Vector b)
208 : {
209 : Vector r;
210 : r.x = a.x + b.x;
211 : r.y = a.y + b.y;
212 : r.z = a.z + b.z;
213 : return r;
214 : }
215 :
216 :
217 : OOINLINE Vector OOVectorInterpolate(Vector a, Vector b, OOScalar where)
218 : {
219 : return make_vector(OOLerp(a.x, b.x, where),
220 : OOLerp(a.y, b.y, where),
221 : OOLerp(a.z, b.z, where));
222 : }
223 :
224 :
225 : OOINLINE Vector OOVectorTowards(Vector a, Vector b, OOScalar where)
226 : {
227 : return make_vector(a.x + b.x * where,
228 : a.y + b.y * where,
229 : a.z + b.z * where);
230 : }
231 :
232 :
233 : OOINLINE Vector vector_subtract(Vector a, Vector b)
234 : {
235 : Vector r;
236 : r.x = a.x - b.x;
237 : r.y = a.y - b.y;
238 : r.z = a.z - b.z;
239 : return r;
240 : }
241 :
242 :
243 : OOINLINE Vector vector_flip(Vector v)
244 : {
245 : return vector_subtract(kZeroVector, v);
246 : }
247 :
248 :
249 : OOINLINE bool vector_equal(Vector a, Vector b)
250 : {
251 : return a.x == b.x && a.y == b.y && a.z == b.z;
252 : }
253 :
254 :
255 : OOINLINE OOScalar magnitude2(Vector vec)
256 : {
257 : return vec.x * vec.x + vec.y * vec.y + vec.z * vec.z;
258 : }
259 :
260 :
261 : OOINLINE OOScalar magnitude(Vector vec)
262 : {
263 : return sqrt(magnitude2(vec));
264 : }
265 :
266 :
267 : OOINLINE Vector vector_normal_or_fallback(Vector vec, Vector fallback)
268 : {
269 : OOScalar mag2 = magnitude2(vec);
270 : if (EXPECT_NOT(mag2 == 0.0f)) return fallback;
271 : return vector_multiply_scalar(vec, 1.0f / sqrt(mag2));
272 : }
273 :
274 :
275 : OOINLINE Vector vector_normal_or_xbasis(Vector vec)
276 : {
277 : return vector_normal_or_fallback(vec, kBasisXVector);
278 : }
279 :
280 :
281 : OOINLINE Vector vector_normal_or_ybasis(Vector vec)
282 : {
283 : return vector_normal_or_fallback(vec, kBasisYVector);
284 : }
285 :
286 :
287 : OOINLINE Vector vector_normal_or_zbasis(Vector vec)
288 : {
289 : return vector_normal_or_fallback(vec, kBasisZVector);
290 : }
291 :
292 :
293 : OOINLINE Vector vector_normal(Vector vec)
294 : {
295 : return vector_normal_or_fallback(vec, kZeroVector);
296 : }
297 :
298 :
299 : OOINLINE OOScalar distance2(Vector v1, Vector v2)
300 : {
301 : return magnitude2(vector_subtract(v1, v2));
302 : }
303 :
304 :
305 : OOINLINE OOScalar distance(Vector v1, Vector v2)
306 : {
307 : return magnitude(vector_subtract(v1, v2));
308 : }
309 :
310 :
311 : OOINLINE Vector true_cross_product(Vector first, Vector second)
312 : {
313 : Vector result;
314 : result.x = (first.y * second.z) - (first.z * second.y);
315 : result.y = (first.z * second.x) - (first.x * second.z);
316 : result.z = (first.x * second.y) - (first.y * second.x);
317 : return result;
318 : }
319 :
320 :
321 : OOINLINE Vector cross_product(Vector first, Vector second)
322 : {
323 : return vector_normal(true_cross_product(first, second));
324 : }
325 :
326 :
327 : OOINLINE OOScalar dot_product (Vector a, Vector b)
328 : {
329 : return (a.x * b.x) + (a.y * b.y) + (a.z * b.z);
330 : }
331 :
332 :
333 : OOINLINE OOScalar triple_product(Vector first, Vector second, Vector third)
334 : {
335 : return dot_product(first, true_cross_product(second, third));
336 : }
337 :
338 :
339 : OOINLINE Vector normal_to_surface(Vector v1, Vector v2, Vector v3)
340 : {
341 : Vector d0, d1;
342 : d0 = vector_subtract(v2, v1);
343 : d1 = vector_subtract(v3, v2);
344 : return cross_product(d0, d1);
345 : }
346 :
347 :
348 : #endif /* INCLUDED_OOMATHS_h */
|