0031431: Visualization, PrsMgr_PresentableObject - simplify HLR computing interface
[occt.git] / src / Graphic3d / Graphic3d_TransformUtils.hxx
CommitLineData
825aa485 1// Created on: 2015-06-18
2// Copyright (c) 2015 OPEN CASCADE SAS
c827ea3a 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 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.
11//
12// Alternatively, this file may be used under the terms of Open CASCADE
13// commercial license or contractual agreement.
14
825aa485 15#ifndef _Graphic3d_TransformUtils_HeaderFile
16#define _Graphic3d_TransformUtils_HeaderFile
c827ea3a 17
3bffef55 18#include <gp_Trsf.hxx>
825aa485 19#include <Graphic3d_Vec.hxx>
20#include <Standard_math.hxx> // M_PI
c827ea3a 21
825aa485 22//! Helper class that implements transformation matrix functionality.
23namespace Graphic3d_TransformUtils
c827ea3a 24{
825aa485 25 template<class T> struct MatrixType {};
c827ea3a 26
825aa485 27 template<> struct MatrixType<Standard_Real> { typedef Graphic3d_Mat4d Mat4; };
c827ea3a 28
825aa485 29 template<> struct MatrixType<Standard_ShortReal> { typedef Graphic3d_Mat4 Mat4; };
c827ea3a 30
825aa485 31 template<class T> struct VectorType {};
c827ea3a 32
825aa485 33 template<> struct VectorType<Standard_Real> {
34 typedef Graphic3d_Vec2d Vec2;
35 typedef Graphic3d_Vec3d Vec3;
36 typedef Graphic3d_Vec4d Vec4;
c827ea3a 37 };
38
825aa485 39 template<> struct VectorType<Standard_ShortReal> {
40 typedef Graphic3d_Vec2 Vec2;
41 typedef Graphic3d_Vec3 Vec3;
42 typedef Graphic3d_Vec4 Vec4;
c827ea3a 43 };
44
1d92133e 45 //! Converts gp_Trsf to Graphic3d_Mat4.
46 template<class T>
47 static void Convert (const gp_Trsf& theTransformation,
48 typename MatrixType<T>::Mat4& theOut);
49
c827ea3a 50 //! Constructs a 3D orthographic projection matrix.
51 template<class T>
52 static void Ortho (typename MatrixType<T>::Mat4& theOut,
825aa485 53 const T theLeft,
54 const T theRight,
55 const T theBottom,
56 const T theTop,
57 const T theZNear,
58 const T theZFar);
c827ea3a 59
60 //! Constructs a 2D orthographic projection matrix.
61 template<class T>
62 static void Ortho2D (typename MatrixType<T>::Mat4& theOut,
825aa485 63 const T theLeft,
64 const T theRight,
65 const T theBottom,
66 const T theTop);
c827ea3a 67
68 //! Maps object coordinates to window coordinates.
69 template<class T>
70 static Standard_Boolean Project (const T theObjX,
71 const T theObjY,
72 const T theObjZ,
73 const typename MatrixType<T>::Mat4& theModViewMat,
74 const typename MatrixType<T>::Mat4& theProjectMat,
75 const Standard_Integer theViewport[4],
76 T& theWinX,
77 T& theWinY,
78 T& theWinZ);
79
80 //! Maps window coordinates to object coordinates.
81 template<class T>
82 static Standard_Boolean UnProject (const T theWinX,
83 const T theWinY,
84 const T theWinZ,
85 const typename MatrixType<T>::Mat4& theModViewMat,
86 const typename MatrixType<T>::Mat4& theProjectMat,
87 const Standard_Integer theViewport[4],
88 T& theObjX,
89 T& theObjY,
90 T& theObjZ);
91
92 //! Constructs a 4x4 rotation matrix.
93 template<class T>
94 static void ConstructRotate (typename MatrixType<T>::Mat4& theOut,
95 T theA,
96 T theX,
97 T theY,
98 T theZ);
99
100 //! Constructs a 4x4 rotation matrix.
101 template<class T>
102 static void Rotate (typename MatrixType<T>::Mat4& theOut,
103 T theA,
104 T theX,
105 T theY,
106 T theZ);
107
108 //! Constructs a 4x4 scaling matrix.
109 template<class T>
110 static void Scale (typename MatrixType<T>::Mat4& theOut,
111 T theX,
112 T theY,
113 T theZ);
114
115 //! Constructs a 4x4 translation matrix.
116 template<class T>
117 static void Translate (typename MatrixType<T>::Mat4& theOut,
118 T theX,
119 T theY,
120 T theZ);
1d92133e 121
122 //! Returns scaling factor from 3x3 affine matrix.
123 template<class T>
124 static Standard_Real ScaleFactor (const typename MatrixType<T>::Mat4& theMatrix);
125}
126
127// =======================================================================
128// function : Convert
129// purpose :
130// =======================================================================
131template<class T>
132void Graphic3d_TransformUtils::Convert (const gp_Trsf& theTransformation,
133 typename MatrixType<T>::Mat4& theOut)
134{
135 theOut.InitIdentity();
136
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);
147
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();
c827ea3a 152}
153
154// =======================================================================
155// function : Rotate
156// purpose : Constructs a 4x4 rotation matrix
157// =======================================================================
158template<class T>
825aa485 159void Graphic3d_TransformUtils::Rotate (typename MatrixType<T>::Mat4& theOut,
160 T theA,
161 T theX,
162 T theY,
163 T theZ)
c827ea3a 164{
165 typename MatrixType<T>::Mat4 aMat;
166 ConstructRotate (aMat, theA, theX, theY, theZ);
167 theOut = theOut * aMat;
168}
169
170// =======================================================================
171// function : Translate
172// purpose : Constructs a 4x4 translation matrix
173// =======================================================================
174template<class T>
825aa485 175void Graphic3d_TransformUtils::Translate (typename MatrixType<T>::Mat4& theOut,
176 T theX,
177 T theY,
178 T theZ)
c827ea3a 179{
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);
184
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);
189
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);
194
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);
199}
200
201// =======================================================================
202// function : Scale
203// purpose : Constructs a 4x4 scaling matrix
204// =======================================================================
205template<class T>
825aa485 206void Graphic3d_TransformUtils::Scale (typename MatrixType<T>::Mat4& theOut,
207 T theX,
208 T theY,
209 T theZ)
c827ea3a 210{
211 theOut.ChangeValue (0, 0) *= theX;
212 theOut.ChangeValue (1, 0) *= theX;
213 theOut.ChangeValue (2, 0) *= theX;
214 theOut.ChangeValue (3, 0) *= theX;
215
216 theOut.ChangeValue (0, 1) *= theY;
217 theOut.ChangeValue (1, 1) *= theY;
218 theOut.ChangeValue (2, 1) *= theY;
219 theOut.ChangeValue (3, 1) *= theY;
220
221 theOut.ChangeValue (0, 2) *= theZ;
222 theOut.ChangeValue (1, 2) *= theZ;
223 theOut.ChangeValue (2, 2) *= theZ;
224 theOut.ChangeValue (3, 2) *= theZ;
225}
226
227// =======================================================================
228// function : ConstructRotate
229// purpose : Constructs a 4x4 rotation matrix
230// =======================================================================
231template<class T>
825aa485 232void Graphic3d_TransformUtils::ConstructRotate (typename MatrixType<T>::Mat4& theOut,
233 T theA,
234 T theX,
235 T theY,
236 T theZ)
c827ea3a 237{
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));
240
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));
244
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));
248
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));
252
825aa485 253 if (isOnlyX) // Rotation only around X.
c827ea3a 254 {
255 theOut.SetValue (1, 1, aCos);
256 theOut.SetValue (2, 2, aCos);
257
258 if (theX < static_cast<T> (0.0))
259 {
260 theOut.SetValue (1, 2, aSin);
261 theOut.SetValue (2, 1, -aSin);
262 }
263 else
264 {
265 theOut.SetValue (1, 2, -aSin);
266 theOut.SetValue (2, 1, aSin);
267 }
268
269 return;
270 }
825aa485 271 else if (isOnlyY) // Rotation only around Y.
c827ea3a 272 {
273 theOut.SetValue (0, 0, aCos);
274 theOut.SetValue (2, 2, aCos);
275
276 if (theY < static_cast<T> (0.0))
277 {
278 theOut.SetValue (0, 2, -aSin);
279 theOut.SetValue (2, 0, aSin);
280 }
281 else
282 {
283 theOut.SetValue (0, 2, aSin);
284 theOut.SetValue (2, 0, -aSin);
285 }
286
287 return;
288 }
825aa485 289 else if (isOnlyZ) // Rotation only around Z.
c827ea3a 290 {
291 theOut.SetValue (0, 0, aCos);
292 theOut.SetValue (1, 1, aCos);
293
294 if (theZ < static_cast<T> (0.0))
295 {
296 theOut.SetValue (0, 1, aSin);
297 theOut.SetValue (1, 0, -aSin);
298 }
299 else
300 {
301 theOut.SetValue (0, 1, -aSin);
302 theOut.SetValue (1, 0, aSin);
303 }
304
305 return;
306 }
307
308 T aNorm = std::sqrt (theX * theX + theY * theY + theZ * theZ);
309
310 if (aNorm <= static_cast<T> (1.0e-4))
311 {
825aa485 312 return; // Negligible rotation.
c827ea3a 313 }
314
315 aNorm = static_cast<T> (1.0) / aNorm;
316
317 theX *= aNorm;
318 theY *= aNorm;
319 theZ *= aNorm;
320
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;
330
331 const T aOneMinusCos = static_cast<T> (1.0) - aCos;
332
333 theOut.SetValue (0, 0, aOneMinusCos * aXX + aCos);
334 theOut.SetValue (0, 1, aOneMinusCos * aXY - aSinZ);
335 theOut.SetValue (0, 2, aOneMinusCos * aZX + aSinY);
336
337 theOut.SetValue (1, 0, aOneMinusCos * aXY + aSinZ);
338 theOut.SetValue (1, 1, aOneMinusCos * aYY + aCos);
339 theOut.SetValue (1, 2, aOneMinusCos * aYZ - aSinX);
340
341 theOut.SetValue (2, 0, aOneMinusCos * aZX - aSinY);
342 theOut.SetValue (2, 1, aOneMinusCos * aYZ + aSinX);
343 theOut.SetValue (2, 2, aOneMinusCos * aZZ + aCos);
344}
345
346// =======================================================================
347// function : Ortho
348// purpose : Constructs a 3D orthographic projection matrix
349// =======================================================================
350template<class T>
825aa485 351void Graphic3d_TransformUtils::Ortho (typename MatrixType<T>::Mat4& theOut,
352 const T theLeft,
353 const T theRight,
354 const T theBottom,
355 const T theTop,
356 const T theZNear,
357 const T theZFar)
c827ea3a 358{
359 theOut.InitIdentity();
360
361 T* aData = theOut.ChangeData();
362
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);
366
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;
370
371 aData[12] = -(theRight + theLeft) * anInvDx;
372 aData[13] = -(theTop + theBottom) * anInvDy;
373 aData[14] = -(theZFar + theZNear) * anInvDz;
374}
375
376// =======================================================================
377// function : Ortho2D
378// purpose : Constructs a 2D orthographic projection matrix
379// =======================================================================
380template<class T>
825aa485 381void Graphic3d_TransformUtils::Ortho2D (typename MatrixType<T>::Mat4& theOut,
382 const T theLeft,
383 const T theRight,
384 const T theBottom,
385 const T theTop)
c827ea3a 386{
387 Ortho (theOut, theLeft, theRight, theBottom, theTop, static_cast<T> (-1.0), static_cast<T> (1.0));
388}
389
390// =======================================================================
391// function : Project
392// purpose : Maps object coordinates to window coordinates
393// =======================================================================
394template<class T>
825aa485 395static Standard_Boolean Graphic3d_TransformUtils::Project (const T theObjX,
396 const T theObjY,
397 const T theObjZ,
398 const typename MatrixType<T>::Mat4& theModViewMat,
399 const typename MatrixType<T>::Mat4& theProjectMat,
400 const Standard_Integer theViewport[4],
401 T& theWinX,
402 T& theWinY,
403 T& theWinZ)
c827ea3a 404{
405 typename VectorType<T>::Vec4 anIn (theObjX, theObjY, theObjZ, static_cast<T> (1.0));
406
407 typename VectorType<T>::Vec4 anOut = theProjectMat * (theModViewMat * anIn);
408
409 if (anOut.w() == static_cast<T> (0.0))
410 {
411 return Standard_False;
412 }
413
414 anOut.w() = static_cast<T> (1.0) / anOut.w();
415
416 anOut.x() *= anOut.w();
417 anOut.y() *= anOut.w();
418 anOut.z() *= anOut.w();
419
825aa485 420 // Map x, y and z to range 0-1.
a79f67f8 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);
c827ea3a 424
825aa485 425 // Map x,y to viewport.
c827ea3a 426 anOut.x() = anOut.x() * theViewport[2] + theViewport[0];
427 anOut.y() = anOut.y() * theViewport[3] + theViewport[1];
428
429 theWinX = anOut.x();
430 theWinY = anOut.y();
431 theWinZ = anOut.z();
432
433 return Standard_True;
434}
435
436// =======================================================================
437// function : UnProject
438// purpose : Maps window coordinates to object coordinates
439// =======================================================================
440template<class T>
825aa485 441static Standard_Boolean Graphic3d_TransformUtils::UnProject (const T theWinX,
442 const T theWinY,
443 const T theWinZ,
444 const typename MatrixType<T>::Mat4& theModViewMat,
445 const typename MatrixType<T>::Mat4& theProjectMat,
446 const Standard_Integer theViewport[4],
447 T& theObjX,
448 T& theObjY,
449 T& theObjZ)
c827ea3a 450{
451 typename MatrixType<T>::Mat4 anUnviewMat;
452
453 if (!(theProjectMat * theModViewMat).Inverted (anUnviewMat))
454 {
455 return Standard_False;
456 }
457
458 typename VectorType<T>::Vec4 anIn (theWinX, theWinY, theWinZ, static_cast<T> (1.0));
459
825aa485 460 // Map x and y from window coordinates.
c827ea3a 461 anIn.x() = (anIn.x() - theViewport[0]) / theViewport[2];
462 anIn.y() = (anIn.y() - theViewport[1]) / theViewport[3];
463
825aa485 464 // Map to range -1 to 1.
c827ea3a 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);
468
469 typename VectorType<T>::Vec4 anOut = anUnviewMat * anIn;
470
471 if (anOut.w() == static_cast<T> (0.0))
472 {
473 return Standard_False;
474 }
475
476 anOut.w() = static_cast<T> (1.0) / anOut.w();
477
478 anOut.x() *= anOut.w();
479 anOut.y() *= anOut.w();
480 anOut.z() *= anOut.w();
481
482 theObjX = anOut.x();
483 theObjY = anOut.y();
484 theObjZ = anOut.z();
485
486 return Standard_True;
487}
488
1d92133e 489// =======================================================================
490// function : ScaleFactor
491// purpose :
492// =======================================================================
493template<class T>
494static Standard_Real Graphic3d_TransformUtils::ScaleFactor (const typename MatrixType<T>::Mat4& theMatrix)
495{
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));
503
504 return Pow (static_cast<Standard_Real> (aDeterminant), 1.0 / 3.0);
505}
506
825aa485 507#endif // _Graphic3d_TransformUtils_HeaderFile