1 // Created on: 2015-06-18
2 // Copyright (c) 2015 OPEN CASCADE SAS
4 // This file is part of Open CASCADE Technology software library.
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License 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.
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
15 #ifndef _Graphic3d_TransformUtils_HeaderFile
16 #define _Graphic3d_TransformUtils_HeaderFile
18 #include <gp_Trsf.hxx>
19 #include <Graphic3d_Vec.hxx>
20 #include <Standard_math.hxx> // M_PI
22 //! Helper class that implements transformation matrix functionality.
23 namespace Graphic3d_TransformUtils
25 template<class T> struct MatrixType {};
27 template<> struct MatrixType<Standard_Real> { typedef Graphic3d_Mat4d Mat4; };
29 template<> struct MatrixType<Standard_ShortReal> { typedef Graphic3d_Mat4 Mat4; };
31 template<class T> struct VectorType {};
33 template<> struct VectorType<Standard_Real> {
34 typedef Graphic3d_Vec2d Vec2;
35 typedef Graphic3d_Vec3d Vec3;
36 typedef Graphic3d_Vec4d Vec4;
39 template<> struct VectorType<Standard_ShortReal> {
40 typedef Graphic3d_Vec2 Vec2;
41 typedef Graphic3d_Vec3 Vec3;
42 typedef Graphic3d_Vec4 Vec4;
45 //! Converts gp_Trsf to Graphic3d_Mat4.
47 static void Convert (const gp_Trsf& theTransformation,
48 typename MatrixType<T>::Mat4& theOut);
50 //! Constructs a 3D orthographic projection matrix.
52 static void Ortho (typename MatrixType<T>::Mat4& theOut,
60 //! Constructs a 2D orthographic projection matrix.
62 static void Ortho2D (typename MatrixType<T>::Mat4& theOut,
68 //! Maps object coordinates to window coordinates.
70 static Standard_Boolean Project (const T theObjX,
73 const typename MatrixType<T>::Mat4& theModViewMat,
74 const typename MatrixType<T>::Mat4& theProjectMat,
75 const Standard_Integer theViewport[4],
80 //! Maps window coordinates to object coordinates.
82 static Standard_Boolean UnProject (const T theWinX,
85 const typename MatrixType<T>::Mat4& theModViewMat,
86 const typename MatrixType<T>::Mat4& theProjectMat,
87 const Standard_Integer theViewport[4],
92 //! Constructs a 4x4 rotation matrix.
94 static void ConstructRotate (typename MatrixType<T>::Mat4& theOut,
100 //! Constructs a 4x4 rotation matrix.
102 static void Rotate (typename MatrixType<T>::Mat4& theOut,
108 //! Constructs a 4x4 scaling matrix.
110 static void Scale (typename MatrixType<T>::Mat4& theOut,
115 //! Constructs a 4x4 translation matrix.
117 static void Translate (typename MatrixType<T>::Mat4& theOut,
122 //! Returns scaling factor from 3x3 affine matrix.
124 static Standard_Real ScaleFactor (const typename MatrixType<T>::Mat4& theMatrix);
127 // =======================================================================
128 // function : Convert
130 // =======================================================================
132 void Graphic3d_TransformUtils::Convert (const gp_Trsf& theTransformation,
133 typename MatrixType<T>::Mat4& theOut)
135 theOut.InitIdentity();
137 // Copy a 3x3 submatrix.
138 theOut.ChangeValue (0, 0) = theTransformation.Value (1, 1);
139 theOut.ChangeValue (0, 1) = theTransformation.Value (1, 2);
140 theOut.ChangeValue (0, 2) = theTransformation.Value (1, 3);
141 theOut.ChangeValue (1, 0) = theTransformation.Value (2, 1);
142 theOut.ChangeValue (1, 1) = theTransformation.Value (2, 2);
143 theOut.ChangeValue (1, 2) = theTransformation.Value (2, 3);
144 theOut.ChangeValue (2, 0) = theTransformation.Value (3, 1);
145 theOut.ChangeValue (2, 1) = theTransformation.Value (3, 2);
146 theOut.ChangeValue (2, 2) = theTransformation.Value (3, 3);
148 // Add a translate component.
149 theOut.ChangeValue (0, 3) = theTransformation.TranslationPart().X();
150 theOut.ChangeValue (1, 3) = theTransformation.TranslationPart().Y();
151 theOut.ChangeValue (2, 3) = theTransformation.TranslationPart().Z();
154 // =======================================================================
156 // purpose : Constructs a 4x4 rotation matrix
157 // =======================================================================
159 void Graphic3d_TransformUtils::Rotate (typename MatrixType<T>::Mat4& theOut,
165 typename MatrixType<T>::Mat4 aMat;
166 ConstructRotate (aMat, theA, theX, theY, theZ);
167 theOut = theOut * aMat;
170 // =======================================================================
171 // function : Translate
172 // purpose : Constructs a 4x4 translation matrix
173 // =======================================================================
175 void Graphic3d_TransformUtils::Translate (typename MatrixType<T>::Mat4& theOut,
180 theOut.ChangeValue (0, 3) = theOut.GetValue (0, 0) * theX +
181 theOut.GetValue (0, 1) * theY +
182 theOut.GetValue (0, 2) * theZ +
183 theOut.GetValue (0, 3);
185 theOut.ChangeValue (1, 3) = theOut.GetValue (1, 0) * theX +
186 theOut.GetValue (1, 1) * theY +
187 theOut.GetValue (1, 2) * theZ +
188 theOut.GetValue (1, 3);
190 theOut.ChangeValue (2, 3) = theOut.GetValue (2, 0) * theX +
191 theOut.GetValue (2, 1) * theY +
192 theOut.GetValue (2, 2) * theZ +
193 theOut.GetValue (2, 3);
195 theOut.ChangeValue (3, 3) = theOut.GetValue (3, 0) * theX +
196 theOut.GetValue (3, 1) * theY +
197 theOut.GetValue (3, 2) * theZ +
198 theOut.GetValue (3, 3);
201 // =======================================================================
203 // purpose : Constructs a 4x4 scaling matrix
204 // =======================================================================
206 void Graphic3d_TransformUtils::Scale (typename MatrixType<T>::Mat4& theOut,
211 theOut.ChangeValue (0, 0) *= theX;
212 theOut.ChangeValue (1, 0) *= theX;
213 theOut.ChangeValue (2, 0) *= theX;
214 theOut.ChangeValue (3, 0) *= theX;
216 theOut.ChangeValue (0, 1) *= theY;
217 theOut.ChangeValue (1, 1) *= theY;
218 theOut.ChangeValue (2, 1) *= theY;
219 theOut.ChangeValue (3, 1) *= theY;
221 theOut.ChangeValue (0, 2) *= theZ;
222 theOut.ChangeValue (1, 2) *= theZ;
223 theOut.ChangeValue (2, 2) *= theZ;
224 theOut.ChangeValue (3, 2) *= theZ;
227 // =======================================================================
228 // function : ConstructRotate
229 // purpose : Constructs a 4x4 rotation matrix
230 // =======================================================================
232 void Graphic3d_TransformUtils::ConstructRotate (typename MatrixType<T>::Mat4& theOut,
238 const T aSin = std::sin (theA * static_cast<T> (M_PI / 180.0));
239 const T aCos = std::cos (theA * static_cast<T> (M_PI / 180.0));
241 const Standard_Boolean isOnlyX = (theX != static_cast<T> (0.0))
242 && (theY == static_cast<T> (0.0))
243 && (theZ == static_cast<T> (0.0));
245 const Standard_Boolean isOnlyY = (theX == static_cast<T> (0.0))
246 && (theY != static_cast<T> (0.0))
247 && (theZ == static_cast<T> (0.0));
249 const Standard_Boolean isOnlyZ = (theX == static_cast<T> (0.0))
250 && (theY == static_cast<T> (0.0))
251 && (theZ != static_cast<T> (0.0));
253 if (isOnlyX) // Rotation only around X.
255 theOut.SetValue (1, 1, aCos);
256 theOut.SetValue (2, 2, aCos);
258 if (theX < static_cast<T> (0.0))
260 theOut.SetValue (1, 2, aSin);
261 theOut.SetValue (2, 1, -aSin);
265 theOut.SetValue (1, 2, -aSin);
266 theOut.SetValue (2, 1, aSin);
271 else if (isOnlyY) // Rotation only around Y.
273 theOut.SetValue (0, 0, aCos);
274 theOut.SetValue (2, 2, aCos);
276 if (theY < static_cast<T> (0.0))
278 theOut.SetValue (0, 2, -aSin);
279 theOut.SetValue (2, 0, aSin);
283 theOut.SetValue (0, 2, aSin);
284 theOut.SetValue (2, 0, -aSin);
289 else if (isOnlyZ) // Rotation only around Z.
291 theOut.SetValue (0, 0, aCos);
292 theOut.SetValue (1, 1, aCos);
294 if (theZ < static_cast<T> (0.0))
296 theOut.SetValue (0, 1, aSin);
297 theOut.SetValue (1, 0, -aSin);
301 theOut.SetValue (0, 1, -aSin);
302 theOut.SetValue (1, 0, aSin);
308 T aNorm = std::sqrt (theX * theX + theY * theY + theZ * theZ);
310 if (aNorm <= static_cast<T> (1.0e-4))
312 return; // Negligible rotation.
315 aNorm = static_cast<T> (1.0) / aNorm;
321 const T aXX = theX * theX;
322 const T aYY = theY * theY;
323 const T aZZ = theZ * theZ;
324 const T aXY = theX * theY;
325 const T aYZ = theY * theZ;
326 const T aZX = theZ * theX;
327 const T aSinX = theX * aSin;
328 const T aSinY = theY * aSin;
329 const T aSinZ = theZ * aSin;
331 const T aOneMinusCos = static_cast<T> (1.0) - aCos;
333 theOut.SetValue (0, 0, aOneMinusCos * aXX + aCos);
334 theOut.SetValue (0, 1, aOneMinusCos * aXY - aSinZ);
335 theOut.SetValue (0, 2, aOneMinusCos * aZX + aSinY);
337 theOut.SetValue (1, 0, aOneMinusCos * aXY + aSinZ);
338 theOut.SetValue (1, 1, aOneMinusCos * aYY + aCos);
339 theOut.SetValue (1, 2, aOneMinusCos * aYZ - aSinX);
341 theOut.SetValue (2, 0, aOneMinusCos * aZX - aSinY);
342 theOut.SetValue (2, 1, aOneMinusCos * aYZ + aSinX);
343 theOut.SetValue (2, 2, aOneMinusCos * aZZ + aCos);
346 // =======================================================================
348 // purpose : Constructs a 3D orthographic projection matrix
349 // =======================================================================
351 void Graphic3d_TransformUtils::Ortho (typename MatrixType<T>::Mat4& theOut,
359 theOut.InitIdentity();
361 T* aData = theOut.ChangeData();
363 const T anInvDx = static_cast<T> (1.0) / (theRight - theLeft);
364 const T anInvDy = static_cast<T> (1.0) / (theTop - theBottom);
365 const T anInvDz = static_cast<T> (1.0) / (theZFar - theZNear);
367 aData[0] = static_cast<T> ( 2.0) * anInvDx;
368 aData[5] = static_cast<T> ( 2.0) * anInvDy;
369 aData[10] = static_cast<T> (-2.0) * anInvDz;
371 aData[12] = -(theRight + theLeft) * anInvDx;
372 aData[13] = -(theTop + theBottom) * anInvDy;
373 aData[14] = -(theZFar + theZNear) * anInvDz;
376 // =======================================================================
377 // function : Ortho2D
378 // purpose : Constructs a 2D orthographic projection matrix
379 // =======================================================================
381 void Graphic3d_TransformUtils::Ortho2D (typename MatrixType<T>::Mat4& theOut,
387 Ortho (theOut, theLeft, theRight, theBottom, theTop, static_cast<T> (-1.0), static_cast<T> (1.0));
390 // =======================================================================
391 // function : Project
392 // purpose : Maps object coordinates to window coordinates
393 // =======================================================================
395 static Standard_Boolean Graphic3d_TransformUtils::Project (const T theObjX,
398 const typename MatrixType<T>::Mat4& theModViewMat,
399 const typename MatrixType<T>::Mat4& theProjectMat,
400 const Standard_Integer theViewport[4],
405 typename VectorType<T>::Vec4 anIn (theObjX, theObjY, theObjZ, static_cast<T> (1.0));
407 typename VectorType<T>::Vec4 anOut = theProjectMat * (theModViewMat * anIn);
409 if (anOut.w() == static_cast<T> (0.0))
411 return Standard_False;
414 anOut.w() = static_cast<T> (1.0) / anOut.w();
416 anOut.x() *= anOut.w();
417 anOut.y() *= anOut.w();
418 anOut.z() *= anOut.w();
420 // Map x, y and z to range 0-1.
421 anOut.x() = anOut.x() * static_cast<T> (0.5) + static_cast<T> (0.5);
422 anOut.y() = anOut.y() * static_cast<T> (0.5) + static_cast<T> (0.5);
423 anOut.z() = anOut.z() * static_cast<T> (0.5) + static_cast<T> (0.5);
425 // Map x,y to viewport.
426 anOut.x() = anOut.x() * theViewport[2] + theViewport[0];
427 anOut.y() = anOut.y() * theViewport[3] + theViewport[1];
433 return Standard_True;
436 // =======================================================================
437 // function : UnProject
438 // purpose : Maps window coordinates to object coordinates
439 // =======================================================================
441 static Standard_Boolean Graphic3d_TransformUtils::UnProject (const T theWinX,
444 const typename MatrixType<T>::Mat4& theModViewMat,
445 const typename MatrixType<T>::Mat4& theProjectMat,
446 const Standard_Integer theViewport[4],
451 typename MatrixType<T>::Mat4 anUnviewMat;
453 if (!(theProjectMat * theModViewMat).Inverted (anUnviewMat))
455 return Standard_False;
458 typename VectorType<T>::Vec4 anIn (theWinX, theWinY, theWinZ, static_cast<T> (1.0));
460 // Map x and y from window coordinates.
461 anIn.x() = (anIn.x() - theViewport[0]) / theViewport[2];
462 anIn.y() = (anIn.y() - theViewport[1]) / theViewport[3];
464 // Map to range -1 to 1.
465 anIn.x() = anIn.x() * static_cast<T> (2.0) - static_cast<T> (1.0);
466 anIn.y() = anIn.y() * static_cast<T> (2.0) - static_cast<T> (1.0);
467 anIn.z() = anIn.z() * static_cast<T> (2.0) - static_cast<T> (1.0);
469 typename VectorType<T>::Vec4 anOut = anUnviewMat * anIn;
471 if (anOut.w() == static_cast<T> (0.0))
473 return Standard_False;
476 anOut.w() = static_cast<T> (1.0) / anOut.w();
478 anOut.x() *= anOut.w();
479 anOut.y() *= anOut.w();
480 anOut.z() *= anOut.w();
486 return Standard_True;
489 // =======================================================================
490 // function : ScaleFactor
492 // =======================================================================
494 static Standard_Real Graphic3d_TransformUtils::ScaleFactor (const typename MatrixType<T>::Mat4& theMatrix)
496 // The determinant of the matrix should give the scale factor (cubed).
497 const T aDeterminant = (theMatrix.GetValue (0, 0) * theMatrix.GetValue (1, 1) * theMatrix.GetValue (2, 2) +
498 theMatrix.GetValue (0, 1) * theMatrix.GetValue (1, 2) * theMatrix.GetValue (2, 0) +
499 theMatrix.GetValue (0, 2) * theMatrix.GetValue (1, 0) * theMatrix.GetValue (2, 1))
500 - (theMatrix.GetValue (0, 2) * theMatrix.GetValue (1, 1) * theMatrix.GetValue (2, 0) +
501 theMatrix.GetValue (0, 0) * theMatrix.GetValue (1, 2) * theMatrix.GetValue (2, 1) +
502 theMatrix.GetValue (0, 1) * theMatrix.GetValue (1, 0) * theMatrix.GetValue (2, 2));
504 return Pow (static_cast<Standard_Real> (aDeterminant), 1.0 / 3.0);
507 #endif // _Graphic3d_TransformUtils_HeaderFile