PolyVox  0.3.0-dev
Open source voxel management library
Vector.inl
Go to the documentation of this file.
1 /*******************************************************************************
2 Copyright (c) 2005-2009 David Williams
3 
4 This software is provided 'as-is', without any express or implied
5 warranty. In no event will the authors be held liable for any damages
6 arising from the use of this software.
7 
8 Permission is granted to anyone to use this software for any purpose,
9 including commercial applications, and to alter it and redistribute it
10 freely, subject to the following restrictions:
11 
12  1. The origin of this software must not be misrepresented; you must not
13  claim that you wrote the original software. If you use this software
14  in a product, an acknowledgment in the product documentation would be
15  appreciated but is not required.
16 
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19 
20  3. This notice may not be removed or altered from any source
21  distribution.
22 *******************************************************************************/
23 
24 namespace PolyVox
25 {
26  //-------------------------- Constructors, etc ---------------------------------
30  template <uint32_t Size, typename StorageType, typename OperationType>
32  {
33  }
34 
39  template <uint32_t Size,typename StorageType, typename OperationType>
41  {
42  for(uint32_t ct = 0; ct < Size; ct++)
43  {
44  m_tElements[ct] = tFillValue;
45  }
46  }
47 
53  template <uint32_t Size,typename StorageType, typename OperationType>
54  Vector<Size,StorageType,OperationType>::Vector(StorageType x, StorageType y)
55  {
56  POLYVOX_STATIC_ASSERT(Size == 2, "This constructor should only be used for vectors with two elements.");
57 
58  m_tElements[0] = x;
59  m_tElements[1] = y;
60  }
61 
68  template <uint32_t Size,typename StorageType, typename OperationType>
69  Vector<Size,StorageType,OperationType>::Vector(StorageType x, StorageType y, StorageType z)
70  {
71  POLYVOX_STATIC_ASSERT(Size == 3, "This constructor should only be used for vectors with three elements.");
72 
73  m_tElements[0] = x;
74  m_tElements[1] = y;
75  m_tElements[2] = z;
76 
77  }
78 
86  template <uint32_t Size,typename StorageType, typename OperationType>
87  Vector<Size,StorageType,OperationType>::Vector(StorageType x, StorageType y, StorageType z, StorageType w)
88  {
89  POLYVOX_STATIC_ASSERT(Size == 4, "This constructor should only be used for vectors with four elements.");
90 
91  m_tElements[0] = x;
92  m_tElements[1] = y;
93  m_tElements[2] = z;
94  m_tElements[3] = w;
95  }
96 
101  template <uint32_t Size, typename StorageType, typename OperationType>
103  {
104  std::memcpy(m_tElements, vector.m_tElements, sizeof(StorageType) * Size);
105  }
106 
116  template <uint32_t Size, typename StorageType, typename OperationType>
117  template <typename CastType>
119  {
120  for(uint32_t ct = 0; ct < Size; ++ct)
121  {
122  m_tElements[ct] = static_cast<StorageType>(vector.getElement(ct));
123  }
124  }
125 
129  template <uint32_t Size, typename StorageType, typename OperationType>
131  {
132  // We put the static asserts in the destructor because there is one one of these,
133  // where as there are multiple constructors.
134 
135  // Force a vector to have a length greater than one. There is no need for a
136  // vector with one element, and supporting this would cause confusion over the
137  // behaviour of the constructor taking a single value, as this fills all elements
138  // to that value rather than just the first one.
139  POLYVOX_STATIC_ASSERT(Size > 1, "Vector must have a length greater than one.");
140  }
141 
147  template <uint32_t Size, typename StorageType, typename OperationType>
149  {
150  if(this == &rhs)
151  {
152  return *this;
153  }
154  std::memcpy(m_tElements, rhs.m_tElements, sizeof(StorageType) * Size);
155  return *this;
156  }
157 
164  template <uint32_t Size, typename StorageType, typename OperationType>
166  {
167  bool equal = true;
168  for(uint32_t ct = 0; ct < Size; ++ct)
169  {
170  if(m_tElements[ct] != rhs.m_tElements[ct])
171  {
172  equal = false;
173  break;
174  }
175  }
176  return equal;
177  }
178 
185  template <uint32_t Size, typename StorageType, typename OperationType>
187  {
188  return !(*this == rhs); //Just call equality operator and invert the result.
189  }
190 
200  template <uint32_t Size, typename StorageType, typename OperationType>
202  {
203  for(uint32_t ct = 0; ct < Size; ++ct)
204  {
205  if (m_tElements[ct] < rhs.m_tElements[ct])
206  return true;
207  if (rhs.m_tElements[ct] < m_tElements[ct])
208  return false;
209  }
210  return false;
211  }
212 
218  template <uint32_t Size, typename StorageType, typename OperationType>
220  {
221  for(uint32_t ct = 0; ct < Size; ++ct)
222  {
223  m_tElements[ct] += rhs.m_tElements[ct];
224  }
225  return *this;
226  }
227 
233  template <uint32_t Size, typename StorageType, typename OperationType>
235  {
236  for(uint32_t ct = 0; ct < Size; ++ct)
237  {
238  m_tElements[ct] -= rhs.m_tElements[ct];
239  }
240  return *this;
241  }
242 
248  template <uint32_t Size, typename StorageType, typename OperationType>
250  {
251  for(uint32_t ct = 0; ct < Size; ++ct)
252  {
253  m_tElements[ct] *= rhs.m_tElements[ct];
254  }
255  return *this;
256  }
257 
263  template <uint32_t Size, typename StorageType, typename OperationType>
265  {
266  for(uint32_t ct = 0; ct < Size; ++ct)
267  {
268  m_tElements[ct] /= rhs.m_tElements[ct];
269  }
270  return *this;
271  }
272 
278  template <uint32_t Size, typename StorageType, typename OperationType>
280  {
281  for(uint32_t ct = 0; ct < Size; ++ct)
282  {
283  m_tElements[ct] *= rhs;
284  }
285  return *this;
286  }
287 
293  template <uint32_t Size, typename StorageType, typename OperationType>
295  {
296  for(uint32_t ct = 0; ct < Size; ++ct)
297  {
298  m_tElements[ct] /= rhs;
299  }
300  return *this;
301  }
302 
309  template <uint32_t Size,typename StorageType, typename OperationType>
311  {
313  result += rhs;
314  return result;
315  }
316 
323  template <uint32_t Size,typename StorageType, typename OperationType>
325  {
327  result -= rhs;
328  return result;
329  }
330 
337  template <uint32_t Size,typename StorageType, typename OperationType>
339  {
341  result *= rhs;
342  return result;
343  }
344 
351  template <uint32_t Size,typename StorageType, typename OperationType>
353  {
355  result /= rhs;
356  return result;
357  }
358 
365  template <uint32_t Size,typename StorageType, typename OperationType>
367  {
369  result *= rhs;
370  return result;
371  }
372 
379  template <uint32_t Size,typename StorageType, typename OperationType>
381  {
383  result /= rhs;
384  return result;
385  }
386 
393  template <uint32_t Size, typename StorageType, typename OperationType>
394  std::ostream& operator<<(std::ostream& os, const Vector<Size, StorageType, OperationType>& vector)
395  {
396  os << "(";
397  for(uint32_t ct = 0; ct < Size; ++ct)
398  {
399  os << vector.getElement(ct);
400  if(ct < (Size-1))
401  {
402  os << ",";
403  }
404  }
405  os << ")";
406  return os;
407  }
408 
414  template <uint32_t Size, typename StorageType, typename OperationType>
416  {
417  POLYVOX_ASSERT(index < Size, "Attempted to access invalid vector element.");
418  return m_tElements[index];
419  }
420 
424  template <uint32_t Size, typename StorageType, typename OperationType>
425  inline StorageType Vector<Size, StorageType, OperationType>::getX(void) const
426  {
427  return m_tElements[0]; // This is fine, a Vector always contains at least two elements.
428  }
429 
433  template <uint32_t Size, typename StorageType, typename OperationType>
434  inline StorageType Vector<Size, StorageType, OperationType>::getY(void) const
435  {
436  return m_tElements[1]; // This is fine, a Vector always contains at least two elements.
437  }
438 
442  template <uint32_t Size, typename StorageType, typename OperationType>
443  inline StorageType Vector<Size, StorageType, OperationType>::getZ(void) const
444  {
445  POLYVOX_STATIC_ASSERT(Size >= 3, "You can only get the 'z' component from a vector with at least three elements.");
446 
447  return m_tElements[2];
448  }
449 
453  template <uint32_t Size, typename StorageType, typename OperationType>
454  inline StorageType Vector<Size, StorageType, OperationType>::getW(void) const
455  {
456  POLYVOX_STATIC_ASSERT(Size >= 4, "You can only get the 'w' component from a vector with at least four elements.");
457 
458  return m_tElements[3];
459  }
460 
465  template <uint32_t Size, typename StorageType, typename OperationType>
466  inline void Vector<Size, StorageType, OperationType>::setElement(uint32_t index, StorageType tValue)
467  {
468  POLYVOX_ASSERT(index < Size, "Attempted to access invalid vector element.");
469  m_tElements[index] = tValue;
470  }
471 
477  template <uint32_t Size,typename StorageType, typename OperationType>
478  inline void Vector<Size,StorageType,OperationType>::setElements(StorageType x, StorageType y)
479  {
480  // This is fine, a Vector always contains at least two elements.
481  m_tElements[0] = x;
482  m_tElements[1] = y;
483  }
484 
491  template <uint32_t Size,typename StorageType, typename OperationType>
492  inline void Vector<Size,StorageType,OperationType>::setElements(StorageType x, StorageType y, StorageType z)
493  {
494  POLYVOX_STATIC_ASSERT(Size >= 3, "You can only use this version of setElements() on a vector with at least three elements.");
495 
496  m_tElements[0] = x;
497  m_tElements[1] = y;
498  m_tElements[2] = z;
499  }
500 
508  template <uint32_t Size,typename StorageType, typename OperationType>
509  inline void Vector<Size,StorageType,OperationType>::setElements(StorageType x, StorageType y, StorageType z, StorageType w)
510  {
511  POLYVOX_STATIC_ASSERT(Size >= 4, "You can only use this version of setElements() on a vector with at least four elements.");
512 
513  m_tElements[0] = x;
514  m_tElements[1] = y;
515  m_tElements[2] = z;
516  m_tElements[3] = w;
517  }
518 
522  template <uint32_t Size, typename StorageType, typename OperationType>
524  {
525  m_tElements[0] = tX; // This is fine, a Vector always contains at least two elements.
526  }
527 
531  template <uint32_t Size, typename StorageType, typename OperationType>
533  {
534  m_tElements[1] = tY; // This is fine, a Vector always contains at least two elements.
535  }
536 
540  template <uint32_t Size, typename StorageType, typename OperationType>
542  {
543  POLYVOX_STATIC_ASSERT(Size >= 3, "You can only set the 'w' component from a vector with at least three elements.");
544 
545  m_tElements[2] = tZ;
546  }
547 
551  template <uint32_t Size, typename StorageType, typename OperationType>
553  {
554  POLYVOX_STATIC_ASSERT(Size >= 4, "You can only set the 'w' component from a vector with at least four elements.");
555 
556  m_tElements[3] = tW;
557  }
558 
563  template <uint32_t Size, typename StorageType, typename OperationType>
565  {
566  return sqrt(static_cast<float>(lengthSquared()));
567  }
568 
572  template <uint32_t Size, typename StorageType, typename OperationType>
574  {
575  OperationType tLengthSquared = static_cast<OperationType>(0);
576  for(uint32_t ct = 0; ct < Size; ++ct)
577  {
578  tLengthSquared += static_cast<OperationType>(m_tElements[ct]) * static_cast<OperationType>(m_tElements[ct]);
579  }
580  return tLengthSquared;
581  }
582 
592  template <uint32_t Size, typename StorageType, typename OperationType>
594  {
595  return acos(static_cast<float>(dot(vector)) / (vector.length() * this->length()));
596  }
597 
610  template <uint32_t Size, typename StorageType, typename OperationType>
612  {
613  StorageType i = vector.getZ() * this->getY() - vector.getY() * this->getZ();
614  StorageType j = vector.getX() * this->getZ() - vector.getZ() * this->getX();
615  StorageType k = vector.getY() * this->getX() - vector.getX() * this->getY();
617  }
618 
626  template <uint32_t Size, typename StorageType, typename OperationType>
628  {
629  OperationType dotProduct = static_cast<OperationType>(0);
630  for(uint32_t ct = 0; ct < Size; ++ct)
631  {
632  dotProduct += static_cast<OperationType>(m_tElements[ct]) * static_cast<OperationType>(rhs.m_tElements[ct]);
633  }
634  return dotProduct;
635  }
636 
644  template <uint32_t Size, typename StorageType, typename OperationType>
646  {
647  float fLength = this->length();
648  for(uint32_t ct = 0; ct < Size; ++ct)
649  {
650  // Standard float rules apply for divide-by-zero
651  m_tElements[ct] /= fLength;
652  POLYVOX_ASSERT(m_tElements[ct] == m_tElements[ct], "Obtained NAN during vector normalisation. Perhaps the input vector was too short?");
653  }
654  }
655 }//namespace PolyVox