1 // 2 // Copyright 2016 Pixar 3 // 4 // Licensed under the Apache License, Version 2.0 (the "Apache License") 5 // with the following modification; you may not use this file except in 6 // compliance with the Apache License and the following modification to it: 7 // Section 6. Trademarks. is deleted and replaced with: 8 // 9 // 6. Trademarks. This License does not grant permission to use the trade 10 // names, trademarks, service marks, or product names of the Licensor 11 // and its affiliates, except as required to comply with Section 4(c) of 12 // the License and to reproduce the content of the NOTICE file. 13 // 14 // You may obtain a copy of the Apache License at 15 // 16 // http://www.apache.org/licenses/LICENSE-2.0 17 // 18 // Unless required by applicable law or agreed to in writing, software 19 // distributed under the Apache License with the above modification is 20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 21 // KIND, either express or implied. See the Apache License for the specific 22 // language governing permissions and limitations under the Apache License. 23 // 24 //////////////////////////////////////////////////////////////////////// 25 // This file is generated by a script. Do not edit directly. Edit the 26 // vec.template.h file to make changes. 27 28 #ifndef PXR_BASE_GF_VEC3F_H 29 #define PXR_BASE_GF_VEC3F_H 30 31 /// \file gf/vec3f.h 32 /// \ingroup group_gf_LinearAlgebra 33 34 #include "pxr/pxr.h" 35 #include "pxr/base/tf/diagnostic.h" 36 #include "pxr/base/gf/api.h" 37 #include "pxr/base/gf/limits.h" 38 #include "pxr/base/gf/traits.h" 39 #include "pxr/base/gf/math.h" 40 41 #include <boost/functional/hash.hpp> 42 43 #include <cstddef> 44 #include <cmath> 45 46 #include <iosfwd> 47 48 PXR_NAMESPACE_OPEN_SCOPE 49 50 class GfVec3f; 51 52 template <> 53 struct GfIsGfVec<class GfVec3f> { static const bool value = true; }; 54 55 /// \class GfVec3f 56 /// \ingroup group_gf_LinearAlgebra 57 /// 58 /// Basic type for a vector of 3 float components. 59 /// 60 /// Represents a vector of 3 components of type \c float. 61 /// It is intended to be fast and simple. 62 /// 63 class GfVec3f 64 { 65 public: 66 /// Scalar element type and dimension. 67 typedef float ScalarType; 68 static const size_t dimension = 3; 69 70 /// Default constructor does no initialization. 71 GfVec3f() = default; 72 73 /// Initialize all elements to a single value. 74 constexpr explicit GfVec3f(float value) 75 : _data{ value, value, value } 76 { 77 } 78 79 /// Initialize all elements with explicit arguments. 80 constexpr GfVec3f(float s0, float s1, float s2) 81 : _data{ s0, s1, s2 } 82 { 83 } 84 85 /// Construct with pointer to values. 86 template <class Scl> 87 constexpr explicit GfVec3f(Scl const *p) 88 : _data{ p[0], p[1], p[2] } 89 { 90 } 91 92 /// Construct from GfVec3d. 93 explicit GfVec3f(class GfVec3d const &other); 94 95 /// Implicitly convert from GfVec3h. 96 GfVec3f(class GfVec3h const &other); 97 98 /// Implicitly convert from GfVec3i. 99 GfVec3f(class GfVec3i const &other); 100 101 /// Create a unit vector along the X-axis. 102 static GfVec3f XAxis() { 103 GfVec3f result(0); 104 result[0] = 1; 105 return result; 106 } 107 /// Create a unit vector along the Y-axis. 108 static GfVec3f YAxis() { 109 GfVec3f result(0); 110 result[1] = 1; 111 return result; 112 } 113 /// Create a unit vector along the Z-axis. 114 static GfVec3f ZAxis() { 115 GfVec3f result(0); 116 result[2] = 1; 117 return result; 118 } 119 120 /// Create a unit vector along the i-th axis, zero-based. Return the zero 121 /// vector if \p i is greater than or equal to 3. 122 static GfVec3f Axis(size_t i) { 123 GfVec3f result(0); 124 if (i < 3) 125 result[i] = 1; 126 return result; 127 } 128 129 /// Set all elements with passed arguments. 130 GfVec3f &Set(float s0, float s1, float s2) { 131 _data[0] = s0; 132 _data[1] = s1; 133 _data[2] = s2; 134 return *this; 135 } 136 137 /// Set all elements with a pointer to data. 138 GfVec3f &Set(float const *a) { 139 return Set(a[0], a[1], a[2]); 140 } 141 142 /// Direct data access. 143 float const *data() const { return _data; } 144 float *data() { return _data; } 145 float const *GetArray() const { return data(); } 146 147 /// Indexing. 148 float const &operator[](size_t i) const { return _data[i]; } 149 float &operator[](size_t i) { return _data[i]; } 150 151 /// Hash. 152 friend inline size_t hash_value(GfVec3f const &vec) { 153 size_t h = 0; 154 boost::hash_combine(h, vec[0]); 155 boost::hash_combine(h, vec[1]); 156 boost::hash_combine(h, vec[2]); 157 return h; 158 } 159 160 /// Equality comparison. 161 bool operator==(GfVec3f const &other) const { 162 return _data[0] == other[0] && 163 _data[1] == other[1] && 164 _data[2] == other[2]; 165 } 166 bool operator!=(GfVec3f const &other) const { 167 return !(*this == other); 168 } 169 170 // TODO Add inequality for other vec types... 171 /// Equality comparison. 172 GF_API 173 bool operator==(class GfVec3d const &other) const; 174 /// Equality comparison. 175 GF_API 176 bool operator==(class GfVec3h const &other) const; 177 /// Equality comparison. 178 GF_API 179 bool operator==(class GfVec3i const &other) const; 180 181 /// Create a vec with negated elements. 182 GfVec3f operator-() const { 183 return GfVec3f(-_data[0], -_data[1], -_data[2]); 184 } 185 186 /// Addition. 187 GfVec3f &operator+=(GfVec3f const &other) { 188 _data[0] += other[0]; 189 _data[1] += other[1]; 190 _data[2] += other[2]; 191 return *this; 192 } 193 friend GfVec3f operator+(GfVec3f const &l, GfVec3f const &r) { 194 return GfVec3f(l) += r; 195 } 196 197 /// Subtraction. 198 GfVec3f &operator-=(GfVec3f const &other) { 199 _data[0] -= other[0]; 200 _data[1] -= other[1]; 201 _data[2] -= other[2]; 202 return *this; 203 } 204 friend GfVec3f operator-(GfVec3f const &l, GfVec3f const &r) { 205 return GfVec3f(l) -= r; 206 } 207 208 /// Multiplication by scalar. 209 GfVec3f &operator*=(double s) { 210 _data[0] *= s; 211 _data[1] *= s; 212 _data[2] *= s; 213 return *this; 214 } 215 GfVec3f operator*(double s) const { 216 return GfVec3f(*this) *= s; 217 } 218 friend GfVec3f operator*(double s, GfVec3f const &v) { 219 return v * s; 220 } 221 222 /// Division by scalar. 223 // TODO should divide by the scalar type. 224 GfVec3f &operator/=(double s) { 225 // TODO This should not multiply by 1/s, it should do the division. 226 // Doing the division is more numerically stable when s is close to 227 // zero. 228 return *this *= (1.0 / s); 229 } 230 GfVec3f operator/(double s) const { 231 return *this * (1.0 / s); 232 } 233 234 /// See GfDot(). 235 float operator*(GfVec3f const &v) const { 236 return _data[0] * v[0] + _data[1] * v[1] + _data[2] * v[2]; 237 } 238 239 /// Returns the projection of \p this onto \p v. That is: 240 /// \code 241 /// v * (*this * v) 242 /// \endcode 243 GfVec3f GetProjection(GfVec3f const &v) const { 244 return v * (*this * v); 245 } 246 247 /// Returns the orthogonal complement of \p this->GetProjection(b). 248 /// That is: 249 /// \code 250 /// *this - this->GetProjection(b) 251 /// \endcode 252 GfVec3f GetComplement(GfVec3f const &b) const { 253 return *this - this->GetProjection(b); 254 } 255 256 /// Squared length. 257 float GetLengthSq() const { 258 return *this * *this; 259 } 260 261 /// Length 262 float GetLength() const { 263 // TODO should use GfSqrt. 264 return sqrt(GetLengthSq()); 265 } 266 267 /// Normalizes the vector in place to unit length, returning the 268 /// length before normalization. If the length of the vector is 269 /// smaller than \p eps, then the vector is set to vector/\c eps. 270 /// The original length of the vector is returned. See also GfNormalize(). 271 /// 272 /// \todo This was fixed for bug 67777. This is a gcc64 optimizer bug. 273 /// By tickling the code, it no longer tries to write into 274 /// an illegal memory address (in the code section of memory). 275 float Normalize(float eps = GF_MIN_VECTOR_LENGTH) { 276 // TODO this seems suspect... suggest dividing by length so long as 277 // length is not zero. 278 float length = GetLength(); 279 *this /= (length > eps) ? length : eps; 280 return length; 281 } 282 283 GfVec3f GetNormalized(float eps = GF_MIN_VECTOR_LENGTH) const { 284 GfVec3f normalized(*this); 285 normalized.Normalize(eps); 286 return normalized; 287 } 288 289 /// Orthogonalize and optionally normalize a set of basis vectors. This 290 /// uses an iterative method that is very stable even when the vectors are 291 /// far from orthogonal (close to colinear). The number of iterations and 292 /// thus the computation time does increase as the vectors become close to 293 /// colinear, however. Returns a bool specifying whether the solution 294 /// converged after a number of iterations. If it did not converge, the 295 /// returned vectors will be as close as possible to orthogonal within the 296 /// iteration limit. Colinear vectors will be unaltered, and the method 297 /// will return false. 298 GF_API 299 static bool OrthogonalizeBasis( 300 GfVec3f *tx, GfVec3f *ty, GfVec3f *tz, 301 const bool normalize, 302 double eps = GF_MIN_ORTHO_TOLERANCE); 303 304 /// Sets \c v1 and \c v2 to unit vectors such that v1, v2 and *this are 305 /// mutually orthogonal. If the length L of *this is smaller than \c eps, 306 /// then v1 and v2 will have magnitude L/eps. As a result, the function 307 /// delivers a continuous result as *this shrinks in length. 308 GF_API 309 void BuildOrthonormalFrame(GfVec3f *v1, GfVec3f *v2, 310 float eps = GF_MIN_VECTOR_LENGTH) const; 311 312 313 private: 314 float _data[3]; 315 }; 316 317 /// Output a GfVec3f. 318 /// \ingroup group_gf_DebuggingOutput 319 GF_API std::ostream& operator<<(std::ostream &, GfVec3f const &); 320 321 322 PXR_NAMESPACE_CLOSE_SCOPE 323 324 #include "pxr/base/gf/vec3d.h" 325 #include "pxr/base/gf/vec3h.h" 326 #include "pxr/base/gf/vec3i.h" 327 328 PXR_NAMESPACE_OPEN_SCOPE 329 330 inline 331 GfVec3f::GfVec3f(class GfVec3d const &other) 332 { 333 _data[0] = other[0]; 334 _data[1] = other[1]; 335 _data[2] = other[2]; 336 } 337 inline 338 GfVec3f::GfVec3f(class GfVec3h const &other) 339 { 340 _data[0] = other[0]; 341 _data[1] = other[1]; 342 _data[2] = other[2]; 343 } 344 inline 345 GfVec3f::GfVec3f(class GfVec3i const &other) 346 { 347 _data[0] = other[0]; 348 _data[1] = other[1]; 349 _data[2] = other[2]; 350 } 351 352 /// Returns component-wise multiplication of vectors \p v1 and \p v2. 353 inline GfVec3f 354 GfCompMult(GfVec3f const &v1, GfVec3f const &v2) { 355 return GfVec3f( 356 v1[0] * v2[0], 357 v1[1] * v2[1], 358 v1[2] * v2[2] 359 ); 360 } 361 362 /// Returns component-wise quotient of vectors \p v1 and \p v2. 363 inline GfVec3f 364 GfCompDiv(GfVec3f const &v1, GfVec3f const &v2) { 365 return GfVec3f( 366 v1[0] / v2[0], 367 v1[1] / v2[1], 368 v1[2] / v2[2] 369 ); 370 } 371 372 /// Returns the dot (inner) product of two vectors. 373 inline float 374 GfDot(GfVec3f const &v1, GfVec3f const &v2) { 375 return v1 * v2; 376 } 377 378 379 /// Returns the geometric length of \c v. 380 inline float 381 GfGetLength(GfVec3f const &v) 382 { 383 return v.GetLength(); 384 } 385 386 /// Normalizes \c *v in place to unit length, returning the length before 387 /// normalization. If the length of \c *v is smaller than \p eps then \c *v is 388 /// set to \c *v/eps. The original length of \c *v is returned. 389 inline float 390 GfNormalize(GfVec3f *v, float eps = GF_MIN_VECTOR_LENGTH) 391 { 392 return v->Normalize(eps); 393 } 394 395 /// Returns a normalized (unit-length) vector with the same direction as \p v. 396 /// If the length of this vector is smaller than \p eps, the vector divided by 397 /// \p eps is returned. 398 inline GfVec3f 399 GfGetNormalized(GfVec3f const &v, float eps = GF_MIN_VECTOR_LENGTH) 400 { 401 return v.GetNormalized(eps); 402 } 403 404 /// Returns the projection of \p a onto \p b. That is: 405 /// \code 406 /// b * (a * b) 407 /// \endcode 408 inline GfVec3f 409 GfGetProjection(GfVec3f const &a, GfVec3f const &b) 410 { 411 return a.GetProjection(b); 412 } 413 414 /// Returns the orthogonal complement of \p a.GetProjection(b). That is: 415 /// \code 416 /// a - a.GetProjection(b) 417 /// \endcode 418 inline GfVec3f 419 GfGetComplement(GfVec3f const &a, GfVec3f const &b) 420 { 421 return a.GetComplement(b); 422 } 423 424 /// Tests for equality within a given tolerance, returning \c true if the 425 /// length of the difference vector is less than or equal to \p tolerance. 426 inline bool 427 GfIsClose(GfVec3f const &v1, GfVec3f const &v2, double tolerance) 428 { 429 GfVec3f delta = v1 - v2; 430 return delta.GetLengthSq() <= tolerance * tolerance; 431 } 432 433 434 GF_API bool 435 GfOrthogonalizeBasis(GfVec3f *tx, GfVec3f *ty, GfVec3f *tz, 436 bool normalize, double eps = GF_MIN_ORTHO_TOLERANCE); 437 438 GF_API void 439 GfBuildOrthonormalFrame(GfVec3f const &v0, 440 GfVec3f* v1, 441 GfVec3f* v2, 442 float eps = GF_MIN_VECTOR_LENGTH); 443 444 /// Returns the cross product of \p v1 and \p v2. 445 inline GfVec3f 446 GfCross(GfVec3f const &v1, GfVec3f const &v2) 447 { 448 return GfVec3f( 449 v1[1] * v2[2] - v1[2] * v2[1], 450 v1[2] * v2[0] - v1[0] * v2[2], 451 v1[0] * v2[1] - v1[1] * v2[0]); 452 } 453 454 /// Returns the cross product of \p v1 and \p v2. 455 /// \see GfCross() 456 inline GfVec3f 457 operator^(GfVec3f const &v1, GfVec3f const &v2) 458 { 459 return GfCross(v1, v2); 460 } 461 462 /// Spherical linear interpolation in three dimensions. 463 GF_API GfVec3f 464 GfSlerp(double alpha, GfVec3f const &v0, GfVec3f const &v1); 465 466 467 468 PXR_NAMESPACE_CLOSE_SCOPE 469 470 #endif // PXR_BASE_GF_VEC3F_H 471