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