0024473: TKMath, BVH - introduce template-based package for Bounding volume hierarchy...
[occt.git] / src / NCollection / NCollection_Vec3.hxx
1 // Created by: Kirill GAVRILOV
2 // Copyright (c) 2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and / or modify it
7 // under the terms of the GNU Lesser General Public version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 #ifndef _NCollection_Vec3_H__
16 #define _NCollection_Vec3_H__
17
18 #include <cstring>
19 #include <cmath>
20 #include <NCollection_Vec2.hxx>
21
22 //! Auxiliary macros to define couple of similar access components as vector methods
23 #define NCOLLECTION_VEC_COMPONENTS_3D(theX, theY, theZ) \
24   const NCollection_Vec3<Element_t> theX##theY##theZ() const { return NCollection_Vec3<Element_t>(theX(), theY(), theZ()); } \
25   const NCollection_Vec3<Element_t> theX##theZ##theY() const { return NCollection_Vec3<Element_t>(theX(), theZ(), theY()); } \
26   const NCollection_Vec3<Element_t> theY##theX##theZ() const { return NCollection_Vec3<Element_t>(theY(), theX(), theZ()); } \
27   const NCollection_Vec3<Element_t> theY##theZ##theX() const { return NCollection_Vec3<Element_t>(theY(), theZ(), theX()); } \
28   const NCollection_Vec3<Element_t> theZ##theY##theX() const { return NCollection_Vec3<Element_t>(theZ(), theY(), theX()); } \
29   const NCollection_Vec3<Element_t> theZ##theX##theY() const { return NCollection_Vec3<Element_t>(theZ(), theX(), theY()); }
30
31 //! Generic 3-components vector.
32 //! To be used as RGB color pixel or XYZ 3D-point.
33 //! The main target for this class - to handle raw low-level arrays (from/to graphic driver etc.).
34 template<typename Element_t>
35 class NCollection_Vec3
36 {
37
38 public:
39
40   //! Returns the number of components.
41   static int Length()
42   {
43     return 3;
44   }
45
46   //! Empty constructor. Construct the zero vector.
47   NCollection_Vec3()
48   {
49     std::memset (this, 0, sizeof(NCollection_Vec3));
50   }
51
52   //! Initialize ALL components of vector within specified value.
53   explicit NCollection_Vec3 (Element_t theValue)
54   {
55     v[0] = v[1] = v[2] = theValue;
56   }
57
58   //! Per-component constructor.
59   explicit NCollection_Vec3 (const Element_t theX,
60                              const Element_t theY,
61                              const Element_t theZ)
62   {
63     v[0] = theX;
64     v[1] = theY;
65     v[2] = theZ;
66   }
67
68   //! Constructor from 2-components vector.
69   explicit NCollection_Vec3 (const NCollection_Vec2<Element_t>& theVec2)
70   {
71     v[0] = theVec2[0];
72     v[1] = theVec2[1];
73     v[2] = Element_t(0);
74   }
75
76   //! Copy constructor.
77   NCollection_Vec3 (const NCollection_Vec3& theVec3)
78   {
79     std::memcpy (this, &theVec3, sizeof(NCollection_Vec3));
80   }
81
82   //! Assignment operator.
83   const NCollection_Vec3& operator= (const NCollection_Vec3& theVec3)
84   {
85     std::memcpy (this, &theVec3, sizeof(NCollection_Vec3));
86     return *this;
87   }
88
89   //! Alias to 1st component as X coordinate in XYZ.
90   Element_t x() const { return v[0]; }
91
92   //! Alias to 1st component as RED channel in RGB.
93   Element_t r() const { return v[0]; }
94
95   //! Alias to 2nd component as Y coordinate in XYZ.
96   Element_t y() const { return v[1]; }
97
98   //! Alias to 2nd component as GREEN channel in RGB.
99   Element_t g() const { return v[1]; }
100
101   //! Alias to 3rd component as Z coordinate in XYZ.
102   Element_t z() const { return v[2]; }
103
104   //! Alias to 3rd component as BLUE channel in RGB.
105   Element_t b() const { return v[2]; }
106
107   //! @return 2 components by their names in specified order (in GLSL-style)
108   NCOLLECTION_VEC_COMPONENTS_2D(x, y)
109   NCOLLECTION_VEC_COMPONENTS_2D(x, z)
110   NCOLLECTION_VEC_COMPONENTS_2D(y, z)
111
112   //! @return 3 components by their names in specified order (in GLSL-style)
113   NCOLLECTION_VEC_COMPONENTS_3D(x, y, z)
114
115   //! Alias to 1st component as X coordinate in XYZ.
116   Element_t& x() { return v[0]; }
117
118   //! Alias to 1st component as RED channel in RGB.
119   Element_t& r() { return v[0]; }
120
121   //! Alias to 2nd component as Y coordinate in XYZ.
122   Element_t& y() { return v[1]; }
123
124   //! Alias to 2nd component as GREEN channel in RGB.
125   Element_t& g() { return v[1]; }
126
127   //! Alias to 3rd component as Z coordinate in XYZ.
128   Element_t& z() { return v[2]; }
129
130   //! Alias to 3rd component as BLUE channel in RGB.
131   Element_t& b() { return v[2]; }
132
133   //! @return XY-components modifiable vector
134   NCollection_Vec2<Element_t>& xy()
135   {
136     return *((NCollection_Vec2<Element_t>* )&v[0]);
137   }
138
139   //! @return YZ-components modifiable vector
140   NCollection_Vec2<Element_t>& yz()
141   {
142     return *((NCollection_Vec2<Element_t>* )&v[1]);
143   }
144
145   //! Raw access to the data (for OpenGL exchange).
146   const Element_t* GetData()    const { return v; }
147         Element_t* ChangeData()       { return v; }
148   operator const   Element_t*() const { return v; }
149   operator         Element_t*()       { return v; }
150
151   //! Compute per-component summary.
152   NCollection_Vec3& operator+= (const NCollection_Vec3& theAdd)
153   {
154     v[0] += theAdd.v[0];
155     v[1] += theAdd.v[1];
156     v[2] += theAdd.v[2];
157     return *this;
158   }
159
160   //! Compute per-component summary.
161   friend NCollection_Vec3 operator+ (const NCollection_Vec3& theLeft,
162                                      const NCollection_Vec3& theRight)
163   {
164     NCollection_Vec3 aSumm = NCollection_Vec3 (theLeft);
165     return aSumm += theRight;
166   }
167
168   //! Unary -.
169   NCollection_Vec3 operator-() const
170   {
171     return NCollection_Vec3 (-x(), -y(), -z());
172   }
173
174   //! Compute per-component subtraction.
175   NCollection_Vec3& operator-= (const NCollection_Vec3& theDec)
176   {
177     v[0] -= theDec.v[0];
178     v[1] -= theDec.v[1];
179     v[2] -= theDec.v[2];
180     return *this;
181   }
182
183   //! Compute per-component subtraction.
184   friend NCollection_Vec3 operator- (const NCollection_Vec3& theLeft,
185                                      const NCollection_Vec3& theRight)
186   {
187     NCollection_Vec3 aSumm = NCollection_Vec3 (theLeft);
188     return aSumm -= theRight;
189   }
190
191   //! Compute per-component multiplication by scale factor.
192   void Multiply (const Element_t theFactor)
193   {
194     v[0] *= theFactor;
195     v[1] *= theFactor;
196     v[2] *= theFactor;
197   }
198
199   //! Compute per-component multiplication.
200   NCollection_Vec3& operator*= (const NCollection_Vec3& theRight)
201   {
202     v[0] *= theRight.v[0];
203     v[1] *= theRight.v[1];
204     v[2] *= theRight.v[2];
205     return *this;
206   }
207
208   //! Compute per-component multiplication.
209   friend NCollection_Vec3 operator* (const NCollection_Vec3& theLeft,
210                                      const NCollection_Vec3& theRight)
211   {
212     NCollection_Vec3 aResult = NCollection_Vec3 (theLeft);
213     return aResult *= theRight;
214   }
215
216   //! Compute per-component multiplication by scale factor.
217   NCollection_Vec3& operator*= (const Element_t theFactor)
218   {
219     Multiply (theFactor);
220     return *this;
221   }
222
223   //! Compute per-component multiplication by scale factor.
224   NCollection_Vec3 operator* (const Element_t theFactor) const
225   {
226     return Multiplied (theFactor);
227   }
228
229   //! Compute per-component multiplication by scale factor.
230   NCollection_Vec3 Multiplied (const Element_t theFactor) const
231   {
232     NCollection_Vec3 aCopyVec3 (*this);
233     aCopyVec3 *= theFactor;
234     return aCopyVec3;
235   }
236
237   //! Compute component-wise minimum of two vectors.
238   NCollection_Vec3 cwiseMin (const NCollection_Vec3& theVec) const
239   {
240     return NCollection_Vec3 (Min (v[0], theVec.v[0]),
241                              Min (v[1], theVec.v[1]),
242                              Min (v[2], theVec.v[2]));
243   }
244
245   //! Compute component-wise maximum of two vectors.
246   NCollection_Vec3 cwiseMax (const NCollection_Vec3& theVec) const
247   {
248     return NCollection_Vec3 (Max (v[0], theVec.v[0]),
249                              Max (v[1], theVec.v[1]),
250                              Max (v[2], theVec.v[2]));
251   }
252
253   //! Compute per-component division by scale factor.
254   NCollection_Vec3& operator/= (const Element_t theInvFactor)
255   {
256     v[0] /= theInvFactor;
257     v[1] /= theInvFactor;
258     v[2] /= theInvFactor;
259     return *this;
260   }
261
262   //! Compute per-component division by scale factor.
263   NCollection_Vec3 operator/ (const Element_t theInvFactor)
264   {
265     NCollection_Vec3 aResult (this);
266     return aResult /= theInvFactor;
267   }
268
269   //! Computes the dot product.
270   Element_t Dot (const NCollection_Vec3& theOther) const
271   {
272     return x() * theOther.x() + y() * theOther.y() + z() * theOther.z();
273   }
274
275   //! Computes the vector modulus (magnitude, length).
276   Element_t Modulus() const
277   {
278     return std::sqrt (x() * x() + y() * y() + z() * z());
279   }
280
281   //! Computes the square of vector modulus (magnitude, length).
282   //! This method may be used for performance tricks.
283   Element_t SquareModulus() const
284   {
285     return x() * x() + y() * y() + z() * z();
286   }
287
288   //! Normalize the vector.
289   void Normalize()
290   {
291     Element_t aModulus = Modulus();
292     if (aModulus != Element_t(0)) // just avoid divide by zero
293     {
294       x() = x() / aModulus;
295       y() = y() / aModulus;
296       z() = z() / aModulus;
297     }
298   }
299
300   //! Normalize the vector.
301   NCollection_Vec3 Normalized() const
302   {
303     NCollection_Vec3 aCopy (*this);
304     aCopy.Normalize();
305     return aCopy;
306   }
307
308   //! Computes the cross product.
309   static NCollection_Vec3 Cross (const NCollection_Vec3& theVec1,
310                                  const NCollection_Vec3& theVec2)
311   {
312     return NCollection_Vec3(theVec1.y() * theVec2.z() - theVec1.z() * theVec2.y(),
313             theVec1.z() * theVec2.x() - theVec1.x() * theVec2.z(),
314             theVec1.x() * theVec2.y() - theVec1.y() * theVec2.x());
315   }
316
317   //! Compute linear interpolation between to vectors.
318   //! @param theT - interpolation coefficient 0..1;
319   //! @return interpolation result.
320   static NCollection_Vec3 GetLERP (const NCollection_Vec3& theFrom,
321                                    const NCollection_Vec3& theTo,
322                                    const Element_t         theT)
323   {
324     return theFrom * (Element_t(1) - theT) + theTo * theT;
325   }
326
327   //! Constuct DX unit vector.
328   static NCollection_Vec3 DX()
329   {
330     return NCollection_Vec3 (Element_t(1), Element_t(0), Element_t(0));
331   }
332
333   //! Constuct DY unit vector.
334   static NCollection_Vec3 DY()
335   {
336     return NCollection_Vec3 (Element_t(0), Element_t(1), Element_t(0));
337   }
338
339   //! Constuct DZ unit vector.
340   static NCollection_Vec3 DZ()
341   {
342     return NCollection_Vec3 (Element_t(0), Element_t(0), Element_t(1));
343   }
344
345 private:
346
347   Element_t v[3]; //!< define the vector as array to avoid structure alignment issues
348
349 };
350
351 //! Optimized concretization for float type.
352 template<> inline NCollection_Vec3<float>& NCollection_Vec3<float>::operator/= (const float theInvFactor)
353 {
354   Multiply (1.0f / theInvFactor);
355   return *this;
356 }
357
358 //! Optimized concretization for double type.
359 template<> inline NCollection_Vec3<double>& NCollection_Vec3<double>::operator/= (const double theInvFactor)
360 {
361   Multiply (1.0 / theInvFactor);
362   return *this;
363 }
364
365 #endif // _NCollection_Vec3_H__