1 // Created on: 2014-09-30
2 // Created by: Denis BOGOLEPOV
3 // Copyright (c) 2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #ifndef _OpenGl_Utils_H__
17 #define _OpenGl_Utils_H__
19 #include <OpenGl_Vec.hxx>
20 #include <NCollection_Vector.hxx>
22 //! Helper class that implements some functionality of GLU library.
23 namespace OpenGl_Utils
26 //! Matrix type selector.
33 struct MatrixType<Standard_Real> {
34 typedef OpenGl_Mat4d Mat4;
38 struct MatrixType<Standard_ShortReal> {
39 typedef OpenGl_Mat4 Mat4;
42 //! Vector type selector.
49 struct VectorType<Standard_Real> {
50 typedef OpenGl_Vec2d Vec2;
51 typedef OpenGl_Vec3d Vec3;
52 typedef OpenGl_Vec4d Vec4;
56 struct VectorType<Standard_ShortReal> {
57 typedef OpenGl_Vec2 Vec2;
58 typedef OpenGl_Vec3 Vec3;
59 typedef OpenGl_Vec4 Vec4;
62 //! Software implementation for OpenGL matrix stack.
68 //! Constructs matrix state object.
76 //! Pushes current matrix into stack.
79 if (++myStackHead >= myStack.Size())
81 myStack.Append (myCurrent);
85 myStack.SetValue (myStackHead, myCurrent);
89 //! Pops matrix from stack to current.
92 Standard_ASSERT_RETURN (myStackHead != -1, "Matrix stack already empty when MatrixState.Pop() called.", );
93 myCurrent = myStack.Value (myStackHead--);
96 //! @return current matrix.
97 const typename MatrixType<T>::Mat4& Current()
102 //! Sets given matrix as current.
103 void SetCurrent (const typename MatrixType<T>::Mat4& theNewCurrent)
105 myCurrent = theNewCurrent;
108 //! Sets given matrix as current.
109 template <typename Other_t>
110 void SetCurrent (const typename MatrixType<Other_t>::Mat4& theNewCurrent)
112 myCurrent.Convert (theNewCurrent);
115 //! Sets current matrix to identity.
118 myCurrent = typename MatrixType<T>::Mat4();
123 NCollection_Vector<typename MatrixType<T>::Mat4> myStack; //!< Collection used to maintenance matrix stack
124 typename MatrixType<T>::Mat4 myCurrent; //!< Current matrix
125 Standard_Integer myStackHead; //!< Index of stack head
129 //! Constructs a 3D orthographic projection matrix.
131 static void Ortho (typename MatrixType<T>::Mat4& theOut,
132 const T theLeft, const T theRight, const T theBottom, const T theTop, const T theZNear, const T theZFar);
134 //! Constructs a 2D orthographic projection matrix.
136 static void Ortho2D (typename MatrixType<T>::Mat4& theOut,
137 const T theLeft, const T theRight, const T theBottom, const T theTop);
139 //! Maps object coordinates to window coordinates.
141 static Standard_Boolean Project (const T theObjX,
144 const typename MatrixType<T>::Mat4& theModViewMat,
145 const typename MatrixType<T>::Mat4& theProjectMat,
146 const Standard_Integer theViewport[4],
151 //! Maps window coordinates to object coordinates.
153 static Standard_Boolean UnProject (const T theWinX,
156 const typename MatrixType<T>::Mat4& theModViewMat,
157 const typename MatrixType<T>::Mat4& theProjectMat,
158 const Standard_Integer theViewport[4],
163 //! Constructs a 4x4 rotation matrix.
165 static void ConstructRotate (typename MatrixType<T>::Mat4& theOut,
171 //! Constructs a 4x4 rotation matrix.
173 static void Rotate (typename MatrixType<T>::Mat4& theOut,
179 //! Constructs a 4x4 scaling matrix.
181 static void Scale (typename MatrixType<T>::Mat4& theOut,
186 //! Constructs a 4x4 translation matrix.
188 static void Translate (typename MatrixType<T>::Mat4& theOut,
195 // =======================================================================
197 // purpose : Constructs a 4x4 rotation matrix
198 // =======================================================================
200 void OpenGl_Utils::Rotate (typename MatrixType<T>::Mat4& theOut,
206 typename MatrixType<T>::Mat4 aMat;
207 ConstructRotate (aMat, theA, theX, theY, theZ);
208 theOut = theOut * aMat;
211 // =======================================================================
212 // function : Translate
213 // purpose : Constructs a 4x4 translation matrix
214 // =======================================================================
216 void OpenGl_Utils::Translate (typename MatrixType<T>::Mat4& theOut,
221 theOut.ChangeValue (0, 3) = theOut.GetValue (0, 0) * theX +
222 theOut.GetValue (0, 1) * theY +
223 theOut.GetValue (0, 2) * theZ +
224 theOut.GetValue (0, 3);
226 theOut.ChangeValue (1, 3) = theOut.GetValue (1, 0) * theX +
227 theOut.GetValue (1, 1) * theY +
228 theOut.GetValue (1, 2) * theZ +
229 theOut.GetValue (1, 3);
231 theOut.ChangeValue (2, 3) = theOut.GetValue (2, 0) * theX +
232 theOut.GetValue (2, 1) * theY +
233 theOut.GetValue (2, 2) * theZ +
234 theOut.GetValue (2, 3);
236 theOut.ChangeValue (3, 3) = theOut.GetValue (3, 0) * theX +
237 theOut.GetValue (3, 1) * theY +
238 theOut.GetValue (3, 2) * theZ +
239 theOut.GetValue (3, 3);
242 // =======================================================================
244 // purpose : Constructs a 4x4 scaling matrix
245 // =======================================================================
247 void OpenGl_Utils::Scale (typename MatrixType<T>::Mat4& theOut,
252 theOut.ChangeValue (0, 0) *= theX;
253 theOut.ChangeValue (1, 0) *= theX;
254 theOut.ChangeValue (2, 0) *= theX;
255 theOut.ChangeValue (3, 0) *= theX;
257 theOut.ChangeValue (0, 1) *= theY;
258 theOut.ChangeValue (1, 1) *= theY;
259 theOut.ChangeValue (2, 1) *= theY;
260 theOut.ChangeValue (3, 1) *= theY;
262 theOut.ChangeValue (0, 2) *= theZ;
263 theOut.ChangeValue (1, 2) *= theZ;
264 theOut.ChangeValue (2, 2) *= theZ;
265 theOut.ChangeValue (3, 2) *= theZ;
268 // =======================================================================
269 // function : ConstructRotate
270 // purpose : Constructs a 4x4 rotation matrix
271 // =======================================================================
273 void OpenGl_Utils::ConstructRotate (typename MatrixType<T>::Mat4& theOut, T theA, T theX, T theY, T theZ)
275 const T aSin = std::sin (theA * static_cast<T> (M_PI / 180.0));
276 const T aCos = std::cos (theA * static_cast<T> (M_PI / 180.0));
278 const Standard_Boolean isOnlyX = (theX != static_cast<T> (0.0))
279 && (theY == static_cast<T> (0.0))
280 && (theZ == static_cast<T> (0.0));
282 const Standard_Boolean isOnlyY = (theX == static_cast<T> (0.0))
283 && (theY != static_cast<T> (0.0))
284 && (theZ == static_cast<T> (0.0));
286 const Standard_Boolean isOnlyZ = (theX == static_cast<T> (0.0))
287 && (theY == static_cast<T> (0.0))
288 && (theZ != static_cast<T> (0.0));
290 if (isOnlyX) // Rotation only around X
292 theOut.SetValue (1, 1, aCos);
293 theOut.SetValue (2, 2, aCos);
295 if (theX < static_cast<T> (0.0))
297 theOut.SetValue (1, 2, aSin);
298 theOut.SetValue (2, 1, -aSin);
302 theOut.SetValue (1, 2, -aSin);
303 theOut.SetValue (2, 1, aSin);
308 else if (isOnlyY) // Rotation only around Y
310 theOut.SetValue (0, 0, aCos);
311 theOut.SetValue (2, 2, aCos);
313 if (theY < static_cast<T> (0.0))
315 theOut.SetValue (0, 2, -aSin);
316 theOut.SetValue (2, 0, aSin);
320 theOut.SetValue (0, 2, aSin);
321 theOut.SetValue (2, 0, -aSin);
326 else if (isOnlyZ) // Rotation only around Z
328 theOut.SetValue (0, 0, aCos);
329 theOut.SetValue (1, 1, aCos);
331 if (theZ < static_cast<T> (0.0))
333 theOut.SetValue (0, 1, aSin);
334 theOut.SetValue (1, 0, -aSin);
338 theOut.SetValue (0, 1, -aSin);
339 theOut.SetValue (1, 0, aSin);
345 T aNorm = std::sqrt (theX * theX + theY * theY + theZ * theZ);
347 if (aNorm <= static_cast<T> (1.0e-4))
349 return; // negligible rotation
352 aNorm = static_cast<T> (1.0) / aNorm;
358 const T aXX = theX * theX;
359 const T aYY = theY * theY;
360 const T aZZ = theZ * theZ;
361 const T aXY = theX * theY;
362 const T aYZ = theY * theZ;
363 const T aZX = theZ * theX;
364 const T aSinX = theX * aSin;
365 const T aSinY = theY * aSin;
366 const T aSinZ = theZ * aSin;
368 const T aOneMinusCos = static_cast<T> (1.0) - aCos;
370 theOut.SetValue (0, 0, aOneMinusCos * aXX + aCos);
371 theOut.SetValue (0, 1, aOneMinusCos * aXY - aSinZ);
372 theOut.SetValue (0, 2, aOneMinusCos * aZX + aSinY);
374 theOut.SetValue (1, 0, aOneMinusCos * aXY + aSinZ);
375 theOut.SetValue (1, 1, aOneMinusCos * aYY + aCos);
376 theOut.SetValue (1, 2, aOneMinusCos * aYZ - aSinX);
378 theOut.SetValue (2, 0, aOneMinusCos * aZX - aSinY);
379 theOut.SetValue (2, 1, aOneMinusCos * aYZ + aSinX);
380 theOut.SetValue (2, 2, aOneMinusCos * aZZ + aCos);
383 // =======================================================================
385 // purpose : Constructs a 3D orthographic projection matrix
386 // =======================================================================
388 void OpenGl_Utils::Ortho (typename MatrixType<T>::Mat4& theOut,
389 const T theLeft, const T theRight, const T theBottom, const T theTop, const T theZNear, const T theZFar)
391 theOut.InitIdentity();
393 T* aData = theOut.ChangeData();
395 const T anInvDx = static_cast<T> (1.0) / (theRight - theLeft);
396 const T anInvDy = static_cast<T> (1.0) / (theTop - theBottom);
397 const T anInvDz = static_cast<T> (1.0) / (theZFar - theZNear);
399 aData[0] = static_cast<T> ( 2.0) * anInvDx;
400 aData[5] = static_cast<T> ( 2.0) * anInvDy;
401 aData[10] = static_cast<T> (-2.0) * anInvDz;
403 aData[12] = -(theRight + theLeft) * anInvDx;
404 aData[13] = -(theTop + theBottom) * anInvDy;
405 aData[14] = -(theZFar + theZNear) * anInvDz;
408 // =======================================================================
409 // function : Ortho2D
410 // purpose : Constructs a 2D orthographic projection matrix
411 // =======================================================================
413 void OpenGl_Utils::Ortho2D (typename MatrixType<T>::Mat4& theOut,
414 const T theLeft, const T theRight, const T theBottom, const T theTop)
416 Ortho (theOut, theLeft, theRight, theBottom, theTop, static_cast<T> (-1.0), static_cast<T> (1.0));
419 // =======================================================================
420 // function : Project
421 // purpose : Maps object coordinates to window coordinates
422 // =======================================================================
424 static Standard_Boolean OpenGl_Utils::Project (const T theObjX,
427 const typename MatrixType<T>::Mat4& theModViewMat,
428 const typename MatrixType<T>::Mat4& theProjectMat,
429 const Standard_Integer theViewport[4],
434 typename VectorType<T>::Vec4 anIn (theObjX, theObjY, theObjZ, static_cast<T> (1.0));
436 typename VectorType<T>::Vec4 anOut = theProjectMat * (theModViewMat * anIn);
438 if (anOut.w() == static_cast<T> (0.0))
440 return Standard_False;
443 anOut.w() = static_cast<T> (1.0) / anOut.w();
445 anOut.x() *= anOut.w();
446 anOut.y() *= anOut.w();
447 anOut.z() *= anOut.w();
449 // Map x, y and z to range 0-1
450 anOut.x() = anOut.x() * static_cast<T> (0.5) + static_cast<T> (0.5);
451 anOut.y() = anOut.y() * static_cast<T> (0.5) + static_cast<T> (0.5);
452 anOut.z() = anOut.z() * static_cast<T> (0.5) + static_cast<T> (0.5);
454 // Map x,y to viewport
455 anOut.x() = anOut.x() * theViewport[2] + theViewport[0];
456 anOut.y() = anOut.y() * theViewport[3] + theViewport[1];
462 return Standard_True;
465 // =======================================================================
466 // function : UnProject
467 // purpose : Maps window coordinates to object coordinates
468 // =======================================================================
470 static Standard_Boolean OpenGl_Utils::UnProject (const T theWinX,
473 const typename MatrixType<T>::Mat4& theModViewMat,
474 const typename MatrixType<T>::Mat4& theProjectMat,
475 const Standard_Integer theViewport[4],
480 typename MatrixType<T>::Mat4 anUnviewMat;
482 if (!(theProjectMat * theModViewMat).Inverted (anUnviewMat))
484 return Standard_False;
487 typename VectorType<T>::Vec4 anIn (theWinX, theWinY, theWinZ, static_cast<T> (1.0));
489 // Map x and y from window coordinates
490 anIn.x() = (anIn.x() - theViewport[0]) / theViewport[2];
491 anIn.y() = (anIn.y() - theViewport[1]) / theViewport[3];
493 // Map to range -1 to 1
494 anIn.x() = anIn.x() * static_cast<T> (2.0) - static_cast<T> (1.0);
495 anIn.y() = anIn.y() * static_cast<T> (2.0) - static_cast<T> (1.0);
496 anIn.z() = anIn.z() * static_cast<T> (2.0) - static_cast<T> (1.0);
498 typename VectorType<T>::Vec4 anOut = anUnviewMat * anIn;
500 if (anOut.w() == static_cast<T> (0.0))
502 return Standard_False;
505 anOut.w() = static_cast<T> (1.0) / anOut.w();
507 anOut.x() *= anOut.w();
508 anOut.y() *= anOut.w();
509 anOut.z() *= anOut.w();
515 return Standard_True;
518 #endif // _OpenGl_Utils_H__