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 <Graphic3d_Vec.hxx>
19 #include <Standard_math.hxx> // M_PI
21 //! Helper class that implements transformation matrix functionality.
22 namespace Graphic3d_TransformUtils
24 template<class T> struct MatrixType {};
26 template<> struct MatrixType<Standard_Real> { typedef Graphic3d_Mat4d Mat4; };
28 template<> struct MatrixType<Standard_ShortReal> { typedef Graphic3d_Mat4 Mat4; };
30 template<class T> struct VectorType {};
32 template<> struct VectorType<Standard_Real> {
33 typedef Graphic3d_Vec2d Vec2;
34 typedef Graphic3d_Vec3d Vec3;
35 typedef Graphic3d_Vec4d Vec4;
38 template<> struct VectorType<Standard_ShortReal> {
39 typedef Graphic3d_Vec2 Vec2;
40 typedef Graphic3d_Vec3 Vec3;
41 typedef Graphic3d_Vec4 Vec4;
44 //! Constructs a 3D orthographic projection matrix.
46 static void Ortho (typename MatrixType<T>::Mat4& theOut,
54 //! Constructs a 2D orthographic projection matrix.
56 static void Ortho2D (typename MatrixType<T>::Mat4& theOut,
62 //! Maps object coordinates to window coordinates.
64 static Standard_Boolean Project (const T theObjX,
67 const typename MatrixType<T>::Mat4& theModViewMat,
68 const typename MatrixType<T>::Mat4& theProjectMat,
69 const Standard_Integer theViewport[4],
74 //! Maps window coordinates to object coordinates.
76 static Standard_Boolean UnProject (const T theWinX,
79 const typename MatrixType<T>::Mat4& theModViewMat,
80 const typename MatrixType<T>::Mat4& theProjectMat,
81 const Standard_Integer theViewport[4],
86 //! Constructs a 4x4 rotation matrix.
88 static void ConstructRotate (typename MatrixType<T>::Mat4& theOut,
94 //! Constructs a 4x4 rotation matrix.
96 static void Rotate (typename MatrixType<T>::Mat4& theOut,
102 //! Constructs a 4x4 scaling matrix.
104 static void Scale (typename MatrixType<T>::Mat4& theOut,
109 //! Constructs a 4x4 translation matrix.
111 static void Translate (typename MatrixType<T>::Mat4& theOut,
117 // =======================================================================
119 // purpose : Constructs a 4x4 rotation matrix
120 // =======================================================================
122 void Graphic3d_TransformUtils::Rotate (typename MatrixType<T>::Mat4& theOut,
128 typename MatrixType<T>::Mat4 aMat;
129 ConstructRotate (aMat, theA, theX, theY, theZ);
130 theOut = theOut * aMat;
133 // =======================================================================
134 // function : Translate
135 // purpose : Constructs a 4x4 translation matrix
136 // =======================================================================
138 void Graphic3d_TransformUtils::Translate (typename MatrixType<T>::Mat4& theOut,
143 theOut.ChangeValue (0, 3) = theOut.GetValue (0, 0) * theX +
144 theOut.GetValue (0, 1) * theY +
145 theOut.GetValue (0, 2) * theZ +
146 theOut.GetValue (0, 3);
148 theOut.ChangeValue (1, 3) = theOut.GetValue (1, 0) * theX +
149 theOut.GetValue (1, 1) * theY +
150 theOut.GetValue (1, 2) * theZ +
151 theOut.GetValue (1, 3);
153 theOut.ChangeValue (2, 3) = theOut.GetValue (2, 0) * theX +
154 theOut.GetValue (2, 1) * theY +
155 theOut.GetValue (2, 2) * theZ +
156 theOut.GetValue (2, 3);
158 theOut.ChangeValue (3, 3) = theOut.GetValue (3, 0) * theX +
159 theOut.GetValue (3, 1) * theY +
160 theOut.GetValue (3, 2) * theZ +
161 theOut.GetValue (3, 3);
164 // =======================================================================
166 // purpose : Constructs a 4x4 scaling matrix
167 // =======================================================================
169 void Graphic3d_TransformUtils::Scale (typename MatrixType<T>::Mat4& theOut,
174 theOut.ChangeValue (0, 0) *= theX;
175 theOut.ChangeValue (1, 0) *= theX;
176 theOut.ChangeValue (2, 0) *= theX;
177 theOut.ChangeValue (3, 0) *= theX;
179 theOut.ChangeValue (0, 1) *= theY;
180 theOut.ChangeValue (1, 1) *= theY;
181 theOut.ChangeValue (2, 1) *= theY;
182 theOut.ChangeValue (3, 1) *= theY;
184 theOut.ChangeValue (0, 2) *= theZ;
185 theOut.ChangeValue (1, 2) *= theZ;
186 theOut.ChangeValue (2, 2) *= theZ;
187 theOut.ChangeValue (3, 2) *= theZ;
190 // =======================================================================
191 // function : ConstructRotate
192 // purpose : Constructs a 4x4 rotation matrix
193 // =======================================================================
195 void Graphic3d_TransformUtils::ConstructRotate (typename MatrixType<T>::Mat4& theOut,
201 const T aSin = std::sin (theA * static_cast<T> (M_PI / 180.0));
202 const T aCos = std::cos (theA * static_cast<T> (M_PI / 180.0));
204 const Standard_Boolean isOnlyX = (theX != static_cast<T> (0.0))
205 && (theY == static_cast<T> (0.0))
206 && (theZ == static_cast<T> (0.0));
208 const Standard_Boolean isOnlyY = (theX == static_cast<T> (0.0))
209 && (theY != static_cast<T> (0.0))
210 && (theZ == static_cast<T> (0.0));
212 const Standard_Boolean isOnlyZ = (theX == static_cast<T> (0.0))
213 && (theY == static_cast<T> (0.0))
214 && (theZ != static_cast<T> (0.0));
216 if (isOnlyX) // Rotation only around X.
218 theOut.SetValue (1, 1, aCos);
219 theOut.SetValue (2, 2, aCos);
221 if (theX < static_cast<T> (0.0))
223 theOut.SetValue (1, 2, aSin);
224 theOut.SetValue (2, 1, -aSin);
228 theOut.SetValue (1, 2, -aSin);
229 theOut.SetValue (2, 1, aSin);
234 else if (isOnlyY) // Rotation only around Y.
236 theOut.SetValue (0, 0, aCos);
237 theOut.SetValue (2, 2, aCos);
239 if (theY < static_cast<T> (0.0))
241 theOut.SetValue (0, 2, -aSin);
242 theOut.SetValue (2, 0, aSin);
246 theOut.SetValue (0, 2, aSin);
247 theOut.SetValue (2, 0, -aSin);
252 else if (isOnlyZ) // Rotation only around Z.
254 theOut.SetValue (0, 0, aCos);
255 theOut.SetValue (1, 1, aCos);
257 if (theZ < static_cast<T> (0.0))
259 theOut.SetValue (0, 1, aSin);
260 theOut.SetValue (1, 0, -aSin);
264 theOut.SetValue (0, 1, -aSin);
265 theOut.SetValue (1, 0, aSin);
271 T aNorm = std::sqrt (theX * theX + theY * theY + theZ * theZ);
273 if (aNorm <= static_cast<T> (1.0e-4))
275 return; // Negligible rotation.
278 aNorm = static_cast<T> (1.0) / aNorm;
284 const T aXX = theX * theX;
285 const T aYY = theY * theY;
286 const T aZZ = theZ * theZ;
287 const T aXY = theX * theY;
288 const T aYZ = theY * theZ;
289 const T aZX = theZ * theX;
290 const T aSinX = theX * aSin;
291 const T aSinY = theY * aSin;
292 const T aSinZ = theZ * aSin;
294 const T aOneMinusCos = static_cast<T> (1.0) - aCos;
296 theOut.SetValue (0, 0, aOneMinusCos * aXX + aCos);
297 theOut.SetValue (0, 1, aOneMinusCos * aXY - aSinZ);
298 theOut.SetValue (0, 2, aOneMinusCos * aZX + aSinY);
300 theOut.SetValue (1, 0, aOneMinusCos * aXY + aSinZ);
301 theOut.SetValue (1, 1, aOneMinusCos * aYY + aCos);
302 theOut.SetValue (1, 2, aOneMinusCos * aYZ - aSinX);
304 theOut.SetValue (2, 0, aOneMinusCos * aZX - aSinY);
305 theOut.SetValue (2, 1, aOneMinusCos * aYZ + aSinX);
306 theOut.SetValue (2, 2, aOneMinusCos * aZZ + aCos);
309 // =======================================================================
311 // purpose : Constructs a 3D orthographic projection matrix
312 // =======================================================================
314 void Graphic3d_TransformUtils::Ortho (typename MatrixType<T>::Mat4& theOut,
322 theOut.InitIdentity();
324 T* aData = theOut.ChangeData();
326 const T anInvDx = static_cast<T> (1.0) / (theRight - theLeft);
327 const T anInvDy = static_cast<T> (1.0) / (theTop - theBottom);
328 const T anInvDz = static_cast<T> (1.0) / (theZFar - theZNear);
330 aData[0] = static_cast<T> ( 2.0) * anInvDx;
331 aData[5] = static_cast<T> ( 2.0) * anInvDy;
332 aData[10] = static_cast<T> (-2.0) * anInvDz;
334 aData[12] = -(theRight + theLeft) * anInvDx;
335 aData[13] = -(theTop + theBottom) * anInvDy;
336 aData[14] = -(theZFar + theZNear) * anInvDz;
339 // =======================================================================
340 // function : Ortho2D
341 // purpose : Constructs a 2D orthographic projection matrix
342 // =======================================================================
344 void Graphic3d_TransformUtils::Ortho2D (typename MatrixType<T>::Mat4& theOut,
350 Ortho (theOut, theLeft, theRight, theBottom, theTop, static_cast<T> (-1.0), static_cast<T> (1.0));
353 // =======================================================================
354 // function : Project
355 // purpose : Maps object coordinates to window coordinates
356 // =======================================================================
358 static Standard_Boolean Graphic3d_TransformUtils::Project (const T theObjX,
361 const typename MatrixType<T>::Mat4& theModViewMat,
362 const typename MatrixType<T>::Mat4& theProjectMat,
363 const Standard_Integer theViewport[4],
368 typename VectorType<T>::Vec4 anIn (theObjX, theObjY, theObjZ, static_cast<T> (1.0));
370 typename VectorType<T>::Vec4 anOut = theProjectMat * (theModViewMat * anIn);
372 if (anOut.w() == static_cast<T> (0.0))
374 return Standard_False;
377 anOut.w() = static_cast<T> (1.0) / anOut.w();
379 anOut.x() *= anOut.w();
380 anOut.y() *= anOut.w();
381 anOut.z() *= anOut.w();
383 // Map x, y and z to range 0-1.
384 anOut.x() = anOut.x() * static_cast<T> (0.5) + static_cast<T> (0.5);
385 anOut.y() = anOut.y() * static_cast<T> (0.5) + static_cast<T> (0.5);
386 anOut.z() = anOut.z() * static_cast<T> (0.5) + static_cast<T> (0.5);
388 // Map x,y to viewport.
389 anOut.x() = anOut.x() * theViewport[2] + theViewport[0];
390 anOut.y() = anOut.y() * theViewport[3] + theViewport[1];
396 return Standard_True;
399 // =======================================================================
400 // function : UnProject
401 // purpose : Maps window coordinates to object coordinates
402 // =======================================================================
404 static Standard_Boolean Graphic3d_TransformUtils::UnProject (const T theWinX,
407 const typename MatrixType<T>::Mat4& theModViewMat,
408 const typename MatrixType<T>::Mat4& theProjectMat,
409 const Standard_Integer theViewport[4],
414 typename MatrixType<T>::Mat4 anUnviewMat;
416 if (!(theProjectMat * theModViewMat).Inverted (anUnviewMat))
418 return Standard_False;
421 typename VectorType<T>::Vec4 anIn (theWinX, theWinY, theWinZ, static_cast<T> (1.0));
423 // Map x and y from window coordinates.
424 anIn.x() = (anIn.x() - theViewport[0]) / theViewport[2];
425 anIn.y() = (anIn.y() - theViewport[1]) / theViewport[3];
427 // Map to range -1 to 1.
428 anIn.x() = anIn.x() * static_cast<T> (2.0) - static_cast<T> (1.0);
429 anIn.y() = anIn.y() * static_cast<T> (2.0) - static_cast<T> (1.0);
430 anIn.z() = anIn.z() * static_cast<T> (2.0) - static_cast<T> (1.0);
432 typename VectorType<T>::Vec4 anOut = anUnviewMat * anIn;
434 if (anOut.w() == static_cast<T> (0.0))
436 return Standard_False;
439 anOut.w() = static_cast<T> (1.0) / anOut.w();
441 anOut.x() *= anOut.w();
442 anOut.y() *= anOut.w();
443 anOut.z() *= anOut.w();
449 return Standard_True;
452 #endif // _Graphic3d_TransformUtils_HeaderFile