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