1 /* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
2 
3 #ifndef SYNCEDFLOAT3_H
4 #define SYNCEDFLOAT3_H
5 
6 #include "System/float3.h"
7 #include "SyncedPrimitiveBase.h"
8 
9 #if defined(SYNCDEBUG) || defined(SYNCCHECK)
10 
11 #include "lib/streflop/streflop_cond.h"
12 #include "SyncedPrimitive.h"
13 #include "System/FastMath.h" //SSE (I)SQRT
14 
15 #include <math.h>
16 
17 /**
18  * @brief SyncedFloat3 class
19  *
20  * Contains a set of 3 float numbers.
21  * Usually used to represent a vector in
22  * space as x/y/z.
23  */
24 struct SyncedFloat3
25 {
26 public:
27 	// value type -> _STRUCT (because no virtual dtor or vtable is required)
CR_DECLARE_STRUCTSyncedFloat328 	CR_DECLARE_STRUCT(SyncedFloat3)
29 
30 	/**
31 	 * @brief Constructor
32 	 *
33 	 * With no parameters, x/y/z are just initialized to 0.
34 	 */
35 	SyncedFloat3() : x(0.0f), y(0.0f), z(0.0f) {}
36 
37 	/**
38 	 * @brief Copy constructor
39 	 */
SyncedFloat3SyncedFloat340 	SyncedFloat3(const SyncedFloat3& f) : x(f.x), y(f.y), z(f.z) {}
41 
42 	/**
43 	 * @brief Conversion from float3
44 	 */
SyncedFloat3SyncedFloat345 	SyncedFloat3(const float3& f) : x(f.x), y(f.y), z(f.z) {}
46 
47 	/**
48 	 * @brief Constructor
49 	 * @param x float x
50 	 * @param y float y
51 	 * @param z float z
52 	 *
53 	 * With parameters, initializes x/y/z to the given floats.
54 	 */
SyncedFloat3SyncedFloat355 	SyncedFloat3(const float x,const float y,const float z)
56 			: x(x), y(y), z(z) {}
57 
58 	/**
59 	 * @brief float[3] Constructor
60 	 * @param f float[3] to assign
61 	 *
62 	 * With parameters, initializes x/y/z to the given float[3].
63 	 */
SyncedFloat3SyncedFloat364 	SyncedFloat3(const float f[3]) : x(f[0]), y(f[1]), z(f[2]) {}
65 
66 	/**
67 	 * @brief operator =
68 	 * @param f float[3] to assign
69 	 *
70 	 * Sets the float3 to the given float[3].
71 	 */
72 	SyncedFloat3& operator= (const float f[3]) {
73 
74 		x = f[0];
75 		y = f[1];
76 		z = f[2];
77 
78 		return *this;
79 	}
80 
81 	/**
82 	 * @brief Copy x, y, z into float[3]
83 	 * @param f float[3] to copy values into
84 	 *
85 	 * Sets the float[3] to this float3.
86 	 */
copyIntoSyncedFloat387 	void copyInto(float f[3]) const {
88 
89 		f[0] = x;
90 		f[1] = y;
91 		f[2] = z;
92 	}
93 
94 
95 	/**
96 	 * @brief operator +
97 	 * @param f float3 reference to add.
98 	 * @return sum of float3s
99 	 *
100 	 * When adding another float3, will
101 	 * calculate the sum of the positions in
102 	 * space (adds the x/y/z components individually)
103 	 */
104 	float3 operator+ (const float3& f) const {
105 		return float3(x+f.x, y+f.y, z+f.z);
106 	}
107 
108 	/**
109 	 * @brief operator +
110 	 * @return sum of float3+float
111 	 * @param f single float to add
112 	 *
113 	 * When adding just a float, the point is
114 	 * increased in all directions by that float.
115 	 */
116 	float3 operator+ (const float f) const {
117 		return float3(x+f, y+f, z+f);
118 	}
119 
120 	/**
121 	 * @brief operator +=
122 	 * @param f float3 reference to add.
123 	 *
124 	 * Just like adding a float3, but updates this
125 	 * float with the new sum.
126 	 */
127 	void operator+= (const float3& f) {
128 
129 		x += f.x;
130 		y += f.y;
131 		z += f.z;
132 	}
133 
134 	/**
135 	 * @brief operator -
136 	 * @param f float3 to subtract
137 	 * @return difference of float3s
138 	 *
139 	 * Decreases the float3 by another float3,
140 	 * subtracting each x/y/z component individually.
141 	 */
142 	float3 operator- (const float3& f) const {
143 		return float3(x-f.x, y-f.y, z-f.z);
144 	}
145 
146 	/**
147 	 * @brief operator -
148 	 * @return inverted float3
149 	 *
150 	 * When negating the float3, inverts all three
151 	 * x/y/z components.
152 	 */
153 	float3 operator- () const {
154 		return float3(-x, -y, -z);
155 	}
156 
157 	/**
158 	 * @brief operator -
159 	 * @return difference of float3 and float
160 	 * @param f float to subtract
161 	 *
162 	 * When subtracting a single fixed float,
163 	 * decreases all three x/y/z components by that amount.
164 	 */
165 	float3 operator- (const float f) const {
166 		return float3(x-f, y-f, z-f);
167 	}
168 
169 	/**
170 	 * @brief operator -=
171 	 * @param f float3 to subtract
172 	 *
173 	 * Same as subtracting a float3, but stores
174 	 * the new float3 inside this one.
175 	 */
176 	void operator-= (const float3& f) {
177 
178 		x -= f.x;
179 		y -= f.y;
180 		z -= f.z;
181 	}
182 
183 	/**
184 	 * @brief operator *
185 	 * @param f float3 to multiply
186 	 * @return product of float3s
187 	 *
188 	 * When multiplying by another float3,
189 	 * multiplies each x/y/z component individually.
190 	 */
191 	float3 operator* (const float3& f) const {
192 		return float3(x*f.x, y*f.y, z*f.z);
193 	}
194 
195 	/**
196 	 * @brief operator *
197 	 * @param f float to multiply
198 	 * @return product of float3 and float
199 	 *
200 	 * When multiplying by a single float, multiplies
201 	 * each x/y/z component by that float.
202 	 */
203 	float3 operator* (const float f) const {
204 		return float3(x*f, y*f, z*f);
205 	}
206 
207 	/**
208 	 * @brief operator *=
209 	 * @param f float3 to multiply
210 	 *
211 	 * Same as multiplying a float3, but stores
212 	 * the new float3 inside this one.
213 	 */
214 	void operator*= (const float3& f) {
215 		x *= f.x;
216 		y *= f.y;
217 		z *= f.z;
218 	}
219 
220 	/**
221 	 * @brief operator *=
222 	 * @param f float to multiply
223 	 *
224 	 * Same as multiplying a float, but stores
225 	 * the new float3 inside this one.
226 	 */
227 	void operator*= (const float f) {
228 		x *= f;
229 		y *= f;
230 		z *= f;
231 	}
232 
233 	/**
234 	 * @brief operator /
235 	 * @param f float3 to divide
236 	 * @return divided float3
237 	 *
238 	 * When dividing by a float3, divides
239 	 * each x/y/z component individually.
240 	 */
241 	float3 operator/ (const float3& f) const {
242 		return float3(x/f.x, y/f.y, z/f.z);
243 	}
244 
245 	/**
246 	 * @brief operator /
247 	 * @param f float to divide
248 	 * @return float3 divided by float
249 	 *
250 	 * When dividing by a single float, divides
251 	 * each x/y/z component by that float.
252 	 */
253 	float3 operator/ (const float f) const {
254 
255 		const float inv = (float) 1.0f / f;
256 		return *this * inv;
257 	}
258 
259 	/**
260 	 * @brief operator /=
261 	 * @param f float3 to divide
262 	 *
263 	 * Same as dividing by a float3, but stores
264 	 * the new values inside this float3.
265 	 */
266 	void operator/= (const float3& f) {
267 
268 		x /= f.x;
269 		y /= f.y;
270 		z /= f.z;
271 	}
272 
273 	/**
274 	 * @brief operator /=
275 	 * @param f float to divide
276 	 *
277 	 * Same as dividing by a single float, but stores
278 	 * the new values inside this float3.
279 	 */
280 	void operator/= (const float f) {
281 
282 		const float inv = (float) 1.f / f;
283 		*this *= inv;
284 	}
285 
286 	/**
287 	 * @brief operator ==
288 	 * @param f float3 to test
289 	 * @return whether float3s are equal under default CMP_EPS tolerance in x/y/z
290 	 *
291 	 * Tests if this float3 is equal to another, by
292 	 * checking each x/y/z component individually.
293 	 */
294 	bool operator== (const float3& f) const {
295 		return (equals(f));
296 	}
297 
298 	/**
299 	 * @brief operator !=
300 	 * @param f float3 to test
301 	 * @return whether float3s are not equal
302 	 *
303 	 * Tests if this float3 is not equal to another, by
304 	 * checking each x/y/z component individually.
305 	 */
306 	bool operator!= (const float3& f) const {
307 		return (!equals(f));
308 	}
309 
310 	/**
311 	 * @brief operator[]
312 	 * @param t index in xyz array
313 	 * @return float component at index
314 	 *
315 	 * Array access for x/y/z components
316 	 * (index 0 is x, index 1 is y, index 2 is z)
317 	 */
318 	SyncedFloat& operator[] (const int t) {
319 		return (&x)[t];
320 	}
321 
322 	/**
323 	 * @brief operator[] const
324 	 * @param t index in xyz array
325 	 * @return const float component at index
326 	 *
327 	 * Same as plain [] operator but used in
328 	 * a const context
329 	 */
330 	const SyncedFloat& operator[] (const int t) const {
331 		return (&x)[t];
332 	}
333 
334 	/**
335 	 * @see operator==
336 	 */
337 	bool equals(const float3& f, const float3& eps = float3(float3::CMP_EPS, float3::CMP_EPS, float3::CMP_EPS)) const {
338 		return math::fabs(x - f.x) <= math::fabs(eps.x * x)
339 			&& math::fabs(y - f.y) <= math::fabs(eps.y * y)
340 			&& math::fabs(z - f.z) <= math::fabs(eps.z * z);
341 	}
342 
343 	/**
344 	 * @brief dot product
345 	 * @param f float3 to use
346 	 * @return dot product of float3s
347 	 *
348 	 * Calculates the dot product of this and
349 	 * another float3 (sums the products of each
350 	 * x/y/z component).
351 	 */
dotSyncedFloat3352 	float dot (const float3& f) const {
353 		return (x * f.x) + (y * f.y) + (z * f.z);
354 	}
355 
356 	/**
357 	 * @brief cross product
358 	 * @param f float3 to use
359 	 * @return cross product of two float3s
360 	 *
361 	 * Calculates the cross product of this and
362 	 * another float3:
363 	 * (y1*z2 - z1*y2, z1*x2 - x1*z2, x1*y2 - y1*x2)
364 	 */
crossSyncedFloat3365 	float3 cross(const float3& f) const {
366 		return float3(
367 				(y * f.z) - (z * f.y),
368 				(z * f.x) - (x * f.z),
369 				(x * f.y) - (y * f.x));
370 	}
371 
372 	/**
373 	 * @brief distance between float3s
374 	 * @param f float3 to compare against
375 	 * @return float distance between float3s
376 	 *
377 	 * Calculates the distance between this float3
378 	 * and another float3 (sums the differences in each
379 	 * x/y/z component, square root for pythagorean theorem)
380 	 */
distanceSyncedFloat3381 	float distance(const float3& f) const {
382 
383 		const float dx = x - f.x;
384 		const float dy = y - f.y;
385 		const float dz = z - f.z;
386 		return (float) math::sqrt(dx*dx + dy*dy + dz*dz);
387 	}
388 
389 	/**
390 	 * @brief distance2D between float3s (only x and z)
391 	 * @param f float3 to compare against
392 	 * @return 2D distance between float3s
393 	 *
394 	 * Calculates the distance between this float3
395 	 * and another float3 2-dimensionally (that is,
396 	 * only using the x and z components).  Sums the
397 	 * differences in the x and z components, square
398 	 * root for pythagorean theorem
399 	 */
distance2DSyncedFloat3400 	float distance2D(const float3& f) const {
401 
402 		const float dx = x - f.x;
403 		const float dz = z - f.z;
404 		return (float) math::sqrt(dx*dx + dz*dz);
405 	}
406 
407 	/**
408 	 * @brief Length of this vector
409 	 * @return float length of vector
410 	 *
411 	 * Returns the length of this vector
412 	 * (squares and sums each x/y/z component,
413 	 * square root for pythagorean theorem)
414 	 */
LengthSyncedFloat3415 	float Length() const {
416 		//assert(x!=0.f || y!=0.f || z!=0.f);
417 		return (float) math::sqrt(SqLength());
418 	}
419 
420 	/**
421 	 * @brief 2-dimensional length of this vector
422 	 * @return 2D float length of vector
423 	 *
424 	 * Returns the 2-dimensional length of this vector
425 	 * (squares and sums only the x and z components,
426 	 * square root for pythagorean theorem)
427 	 */
Length2DSyncedFloat3428 	float Length2D() const {
429 		//assert(x!=0.f || y!=0.f || z!=0.f);
430 		return (float) math::sqrt(SqLength2D());
431 	}
432 
433 	/**
434 	 * @brief normalizes the vector using one of Normalize implementations
435 	 * @return pointer to self
436 	 *
437 	 * Normalizes the vector by dividing each
438 	 * x/y/z component by the vector's length.
439 	 */
NormalizeSyncedFloat3440 	SyncedFloat3& Normalize() {
441 #if defined(__SUPPORT_SNAN__)
442 		// this can only be invoked by sim thread
443 		assert(SqLength() > float3::NORMALIZE_EPS);
444 		return UnsafeNormalize();
445 #else
446 		return SafeNormalize();
447 #endif
448 	}
449 
450 	/**
451 	 * @brief normalizes the vector without checking for zero vector
452 	 * @return pointer to self
453 	 *
454 	 * Normalizes the vector by dividing each
455 	 * x/y/z component by the vector's length.
456 	 */
UnsafeNormalizeSyncedFloat3457 	SyncedFloat3& UnsafeNormalize() {
458 		*this *= math::isqrt(SqLength());
459 		return *this;
460 	}
461 
462 
463 	/**
464 	 * @brief normalizes the vector safely (check for *this == ZeroVector)
465 	 * @return pointer to self
466 	 *
467 	 * Normalizes the vector by dividing each
468 	 * x/y/z component by the vector's length.
469 	 */
SafeNormalizeSyncedFloat3470 	SyncedFloat3& SafeNormalize() {
471 
472 		const float sql = SqLength();
473 		if (likely(sql > float3::NORMALIZE_EPS)) {
474 			*this *= math::isqrt(sql);
475 		}
476 
477 		return *this;
478 	}
479 
480 
481 	/**
482 	 * @brief normalizes the vector approximately
483 	 * @return pointer to self
484 	 *
485 	 * Normalizes the vector by dividing each x/y/z component by
486 	 * the vector's approx. length.
487 	 */
ANormalizeSyncedFloat3488 	SyncedFloat3& ANormalize() {
489 #if defined(__SUPPORT_SNAN__)
490 		// this can only be invoked by sim thread
491 		assert(SqLength() > float3::NORMALIZE_EPS);
492 		return UnsafeANormalize();
493 #else
494 		return SafeANormalize();
495 #endif
496 	}
497 
498 
499 	/**
500 	 * @brief normalizes the vector approximately without checking
501 	 *        for ZeroVector
502 	 * @return pointer to self
503 	 *
504 	 * Normalizes the vector by dividing each x/y/z component by
505 	 * the vector's approx. length.
506 	 */
UnsafeANormalizeSyncedFloat3507 	SyncedFloat3& UnsafeANormalize() {
508 		*this *= fastmath::isqrt(SqLength());
509 		return *this;
510 	}
511 
512 
513 	/**
514 	 * @brief normalizes the vector approximately and safely
515 	 * @return pointer to self
516 	 *
517 	 * Normalizes the vector by dividing each x/y/z component by
518 	 * the vector's approximate length, if (this != ZeroVector),
519 	 * else do nothing.
520 	 */
SafeANormalizeSyncedFloat3521 	SyncedFloat3& SafeANormalize() {
522 
523 		const float sql = SqLength();
524 		if (likely(sql > float3::NORMALIZE_EPS)) {
525 			*this *= fastmath::isqrt(sql);
526 		}
527 
528 		return *this;
529 	}
530 
531 
532 	/**
533 	 * @brief length squared
534 	 * @return length squared
535 	 *
536 	 * Returns the length of this vector squared.
537 	 */
SqLengthSyncedFloat3538 	float SqLength() const {
539 		return x*x + y*y + z*z;
540 	}
541 
542 	/**
543 	 * @brief 2-dimensional length squared
544 	 * @return 2D length squared
545 	 *
546 	 * Returns the 2-dimensional length of this
547 	 * vector squared.
548 	 */
SqLength2DSyncedFloat3549 	float SqLength2D() const {
550 		return x*x + z*z;
551 	}
552 
553 
554 	/**
555 	 * @brief SqDistance between float3s squared
556 	 * @param f float3 to compare against
557 	 * @return float squared distance between float3s
558 	 *
559 	 * Returns the squared distance of 2 float3s
560 	 */
SqDistanceSyncedFloat3561 	float SqDistance(const float3& f) const {
562 
563 		const float dx = x - f.x;
564 		const float dy = y - f.y;
565 		const float dz = z - f.z;
566 		return (float)(dx*dx + dy*dy + dz*dz);
567 	}
568 
569 
570 	/**
571 	 * @brief SqDistance2D between float3s (only x and z)
572 	 * @param f float3 to compare against
573 	 * @return 2D squared distance between float3s
574 	 *
575 	 * Returns the squared 2d-distance of 2 float3s
576 	 */
SqDistance2DSyncedFloat3577 	float SqDistance2D(const float3& f) const {
578 
579 		const float dx = x - f.x;
580 		const float dz = z - f.z;
581 		return (float)(dx*dx + dz*dz);
582 	}
583 
584 
585 	/**
586 	 * @brief Check against FaceHeightmap bounds
587 	 *
588 	 * Check if this vector is in bounds [0 .. gs->mapxy-1]
589 	 * @note THIS IS THE WRONG SPACE! _ALL_ WORLD SPACE POSITIONS SHOULD BE IN VertexHeightmap RESOLUTION!
590 	 */
591 	bool IsInBounds() const;
592 
593 	/**
594 	 * @brief Clamps to FaceHeightmap
595 	 *
596 	 * Clamps to the `face heightmap` resolution [0 .. gs->mapxy-1]
597 	 * @note THIS IS THE WRONG SPACE! _ALL_ WORLD SPACE POSITIONS SHOULD BE IN VertexHeightmap RESOLUTION!
598 	 */
599 	void ClampInBounds();
600 
601 	/**
602 	 * @brief Clamps to VertexHeightmap
603 	 *
604 	 * Clamps to the `vertex heightmap`/`opengl space` resolution [0 .. gs->mapxy]
605 	 * @note USE THIS!
606 	 */
607 	void ClampInMap();
cClampInMapSyncedFloat3608 	float3 cClampInMap() const { SyncedFloat3 f = *this; f.ClampInMap(); return f; }
609 
610 	/**
611 	 * @brief cast operator
612 	 *
613 	 * @return a float3 with the same x/y/z components as this float3
614 	 */
float3SyncedFloat3615 	operator float3() const { return float3(x, y, z); }
616 
AssertNaNsSyncedFloat3617 	void AssertNaNs() const {
618 		assert(!isnanf(x) && !__isinff(x));
619 		assert(!isnanf(y) && !__isinff(y));
620 		assert(!isnanf(z) && !__isinff(z));
621 	}
622 
623 public:
624 	SyncedFloat x; ///< x component
625 	SyncedFloat y; ///< y component
626 	SyncedFloat z; ///< z component
627 };
628 
629 #else // SYNCDEBUG || SYNCCHECK
630 
631 typedef float3 SyncedFloat3;
632 
633 #endif // !SYNCDEBUG && !SYNCCHECK
634 
635 namespace Sync {
636 	/**
637 	 * @brief Specialization of Assert to better differentiate the components.
638 	 */
Assert(const SyncedFloat3 & f)639 	static inline void Assert(const SyncedFloat3& f) {
640 		Assert(f.x, "assert-x");
641 		Assert(f.y, "assert-y");
642 		Assert(f.z, "assert-z");
643 	}
644 }
645 
646 #endif // SYNCEDFLOAT3_H
647