0024393: Visualization - objects position with enchanced precision
[occt.git] / src / Graphic3d / Graphic3d_TransformPers.hxx
CommitLineData
825aa485 1// Created on: 2015-06-18
2// Created by: Anton POLETAEV
3// Copyright (c) 2015 OPEN CASCADE SAS
4//
5// This file is part of Open CASCADE Technology software library.
6//
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.
12//
13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
15
16#ifndef _Graphic3d_TransformPers_HeaderFile
17#define _Graphic3d_TransformPers_HeaderFile
18
778cd667 19#include <Aspect_TypeOfTriedronPosition.hxx>
825aa485 20#include <Bnd_Box.hxx>
21#include <BVH_Box.hxx>
3fe9ce0e 22#include <Graphic3d_Camera.hxx>
825aa485 23#include <Graphic3d_TransformUtils.hxx>
24#include <Graphic3d_TransModeFlags.hxx>
778cd667 25#include <Graphic3d_Vec.hxx>
825aa485 26#include <NCollection_Mat4.hxx>
778cd667 27
28DEFINE_STANDARD_HANDLE(Graphic3d_TransformPers, Standard_Transient)
825aa485 29
30//! Class for keeping and computing transformation persistence.
778cd667 31//! Note that instance of this class can not define
32//! no transformation persistence Graphic3d_TMF_None - NULL handle should be used for this purpose.
33class Graphic3d_TransformPers : public Standard_Transient
825aa485 34{
778cd667 35 DEFINE_STANDARD_RTTIEXT(Graphic3d_TransformPers, Standard_Transient)
825aa485 36public:
37
778cd667 38 //! Return true if specified mode is zoom/rotate transformation persistence.
39 static Standard_Boolean IsZoomOrRotate (Graphic3d_TransModeFlags theMode)
40 {
41 return (theMode & (Graphic3d_TMF_ZoomPers | Graphic3d_TMF_RotatePers)) != 0;
42 }
43
44 //! Return true if specified mode is 2d/trihedron transformation persistence.
45 static Standard_Boolean IsTrihedronOr2d (Graphic3d_TransModeFlags theMode)
46 {
47 return (theMode & (Graphic3d_TMF_TriedronPers | Graphic3d_TMF_2d)) != 0;
48 }
825aa485 49
778cd667 50 //! Create Graphic3d_TransformPers instance from deprecated parameters set
51 //! decoding 2D corner + offset parameters from 3D point.
52 Standard_EXPORT static Handle(Graphic3d_TransformPers) FromDeprecatedParams (Graphic3d_TransModeFlags theFlag,
53 const gp_Pnt& thePoint);
54
55public:
56
57 //! Set transformation persistence.
58 Graphic3d_TransformPers (const Graphic3d_TransModeFlags theMode)
59 : myMode (theMode)
60 {
61 if (IsZoomOrRotate (theMode))
62 {
63 SetPersistence (theMode, gp_Pnt(0.0, 0.0, 0.0));
64 }
65 else if (IsTrihedronOr2d (theMode))
66 {
67 SetPersistence (theMode, Aspect_TOTP_LEFT_LOWER, Graphic3d_Vec2i (0, 0));
68 }
69 else
70 {
71 Standard_ProgramError::Raise ("Graphic3d_TransformPers::SetPersistence(), wrong persistence mode.");
72 }
73 }
74
75 //! Set Zoom/Rotate transformation persistence with an anchor 3D point.
76 //! Throws an exception if persistence mode is not Graphic3d_TMF_ZoomPers, Graphic3d_TMF_ZoomRotatePers or Graphic3d_TMF_RotatePers.
77 Graphic3d_TransformPers (const Graphic3d_TransModeFlags theMode,
78 const gp_Pnt& thePnt)
79 : myMode (Graphic3d_TMF_None)
80 {
81 SetPersistence (theMode, thePnt);
82 }
83
84 //! Set 2d/trihedron transformation persistence with a corner and 2D offset.
85 //! Throws an exception if persistence mode is not Graphic3d_TMF_TriedronPers or Graphic3d_TMF_2d.
86 //! The offset is a positive displacement from the view corner in pixels.
87 Graphic3d_TransformPers (const Graphic3d_TransModeFlags theMode,
88 const Aspect_TypeOfTriedronPosition theCorner,
89 const Graphic3d_Vec2i& theOffset = Graphic3d_Vec2i (0, 0))
90 : myMode (Graphic3d_TMF_None)
91 {
92 SetPersistence (theMode, theCorner, theOffset);
93 }
94
95 //! Return true for Graphic3d_TMF_ZoomPers, Graphic3d_TMF_ZoomRotatePers or Graphic3d_TMF_RotatePers modes.
96 Standard_Boolean IsZoomOrRotate() const { return IsZoomOrRotate (myMode); }
97
98 //! Return true for Graphic3d_TMF_TriedronPers and Graphic3d_TMF_2d modes.
99 Standard_Boolean IsTrihedronOr2d() const { return IsTrihedronOr2d (myMode); }
825aa485 100
101 //! Transformation persistence mode flags.
778cd667 102 Graphic3d_TransModeFlags Mode() const { return myMode; }
825aa485 103
778cd667 104 //! Transformation persistence mode flags.
105 Graphic3d_TransModeFlags Flags() const { return myMode; }
106
107 //! Set Zoom/Rotate transformation persistence with an anchor 3D point.
108 //! Throws an exception if persistence mode is not Graphic3d_TMF_ZoomPers, Graphic3d_TMF_ZoomRotatePers or Graphic3d_TMF_RotatePers.
109 void SetPersistence (const Graphic3d_TransModeFlags theMode,
110 const gp_Pnt& thePnt)
111 {
112 if (!IsZoomOrRotate (theMode))
113 {
114 Standard_ProgramError::Raise ("Graphic3d_TransformPers::SetPersistence(), wrong persistence mode.");
115 }
116
117 myMode = theMode;
118 myParams.Params3d.PntX = thePnt.X();
119 myParams.Params3d.PntY = thePnt.Y();
120 myParams.Params3d.PntZ = thePnt.Z();
121 }
122
123 //! Set 2d/trihedron transformation persistence with a corner and 2D offset.
124 //! Throws an exception if persistence mode is not Graphic3d_TMF_TriedronPers or Graphic3d_TMF_2d.
125 void SetPersistence (const Graphic3d_TransModeFlags theMode,
126 const Aspect_TypeOfTriedronPosition theCorner,
127 const Graphic3d_Vec2i& theOffset)
128 {
129 if (!IsTrihedronOr2d (theMode))
130 {
131 Standard_ProgramError::Raise ("Graphic3d_TransformPers::SetPersistence(), wrong persistence mode.");
132 }
133
134 myMode = theMode;
135 myParams.Params2d.Corner = theCorner;
136 myParams.Params2d.OffsetX = theOffset.x();
137 myParams.Params2d.OffsetY = theOffset.y();
138 }
139
140public:
141
142 //! Return the anchor point for zoom/rotate transformation persistence.
143 gp_Pnt AnchorPoint() const
144 {
145 if (!IsZoomOrRotate())
146 {
147 Standard_ProgramError::Raise ("Graphic3d_TransformPers::AnchorPoint(), wrong persistence mode.");
148 }
149
150 return gp_Pnt (myParams.Params3d.PntX, myParams.Params3d.PntY, myParams.Params3d.PntZ);
151 }
152
153 //! Set the anchor point for zoom/rotate transformation persistence.
154 void SetAnchorPoint (const gp_Pnt& thePnt)
155 {
156 if (!IsZoomOrRotate())
157 {
158 Standard_ProgramError::Raise ("Graphic3d_TransformPers::SetAnchorPoint(), wrong persistence mode.");
159 }
160
161 myParams.Params3d.PntX = thePnt.X();
162 myParams.Params3d.PntY = thePnt.Y();
163 myParams.Params3d.PntZ = thePnt.Z();
164 }
165
166 //! Return the corner for 2d/trihedron transformation persistence.
167 Aspect_TypeOfTriedronPosition Corner2d() const
168 {
169 if (!IsTrihedronOr2d())
170 {
171 Standard_ProgramError::Raise ("Graphic3d_TransformPers::Corner2d(), wrong persistence mode.");
172 }
173
174 return myParams.Params2d.Corner;
175 }
176
177 //! Set the corner for 2d/trihedron transformation persistence.
178 void SetCorner2d (const Aspect_TypeOfTriedronPosition thePos)
179 {
180 if (!IsTrihedronOr2d())
181 {
182 Standard_ProgramError::Raise ("Graphic3d_TransformPers::SetCorner2d(), wrong persistence mode.");
183 }
184
185 myParams.Params2d.Corner = thePos;
186 }
187
188 //! Return the offset from the corner for 2d/trihedron transformation persistence.
189 Graphic3d_Vec2i Offset2d() const
190 {
191 if (!IsTrihedronOr2d())
192 {
193 Standard_ProgramError::Raise ("Graphic3d_TransformPers::Offset2d(), wrong persistence mode.");
194 }
195
196 return Graphic3d_Vec2i (myParams.Params2d.OffsetX, myParams.Params2d.OffsetY);
197 }
198
199 //! Set the offset from the corner for 2d/trihedron transformation persistence.
200 void SetOffset2d (const Graphic3d_Vec2i& theOffset)
201 {
202 if (!IsTrihedronOr2d())
203 {
204 Standard_ProgramError::Raise ("Graphic3d_TransformPers::SetOffset2d(), wrong persistence mode.");
205 }
206
207 myParams.Params2d.OffsetX = theOffset.x();
208 myParams.Params2d.OffsetY = theOffset.y();
209 }
825aa485 210
211public:
212
213 //! Apply transformation to bounding box of presentation.
3fe9ce0e 214 //! @param theCamera [in] camera definition
825aa485 215 //! @param theProjection [in] the projection transformation matrix.
216 //! @param theWorldView [in] the world view transformation matrix.
217 //! @param theViewportWidth [in] the width of viewport (for 2d persistence).
218 //! @param theViewportHeight [in] the height of viewport (for 2d persistence).
219 //! @param theBoundingBox [in/out] the bounding box to transform.
220 template<class T>
3fe9ce0e 221 void Apply (const Handle(Graphic3d_Camera)& theCamera,
222 const NCollection_Mat4<T>& theProjection,
825aa485 223 const NCollection_Mat4<T>& theWorldView,
224 const Standard_Integer theViewportWidth,
225 const Standard_Integer theViewportHeight,
226 Bnd_Box& theBoundingBox) const;
227
228 //! Apply transformation to bounding box of presentation
3fe9ce0e 229 //! @param theCamera [in] camera definition
825aa485 230 //! @param theProjection [in] the projection transformation matrix.
231 //! @param theWorldView [in] the world view transformation matrix.
232 //! @param theViewportWidth [in] the width of viewport (for 2d persistence).
233 //! @param theViewportHeight [in] the height of viewport (for 2d persistence).
234 //! @param theBoundingBox [in/out] the bounding box to transform.
235 template<class T>
3fe9ce0e 236 void Apply (const Handle(Graphic3d_Camera)& theCamera,
237 const NCollection_Mat4<T>& theProjection,
825aa485 238 const NCollection_Mat4<T>& theWorldView,
239 const Standard_Integer theViewportWidth,
240 const Standard_Integer theViewportHeight,
7c3ef2f7 241 BVH_Box<T, 3>& theBoundingBox) const;
825aa485 242
243 //! Compute transformation.
244 //! Computed matrix can be applied to model world transformation
245 //! of an object to implement effect of transformation persistence.
3fe9ce0e 246 //! @param theCamera [in] camera definition
825aa485 247 //! @param theProjection [in] the projection transformation matrix.
248 //! @param theWorldView [in] the world view transformation matrix.
249 //! @param theViewportWidth [in] the width of viewport (for 2d persistence).
250 //! @param theViewportHeight [in] the height of viewport (for 2d persistence).
251 //! @return transformation matrix to be applied to model world transformation of an object.
252 template<class T>
3fe9ce0e 253 NCollection_Mat4<T> Compute (const Handle(Graphic3d_Camera)& theCamera,
254 const NCollection_Mat4<T>& theProjection,
825aa485 255 const NCollection_Mat4<T>& theWorldView,
256 const Standard_Integer theViewportWidth,
257 const Standard_Integer theViewportHeight) const;
258
71d8ccc7 259 //! Apply transformation persistence on specified matrices.
260 //! @param theCamera camera definition
261 //! @param theProjection projection matrix to modify
262 //! @param theWorldView world-view matrix to modify
263 //! @param theViewportWidth viewport width
264 //! @param theViewportHeight viewport height
825aa485 265 template<class T>
3fe9ce0e 266 void Apply (const Handle(Graphic3d_Camera)& theCamera,
778cd667 267 const NCollection_Mat4<T>& theProjection,
825aa485 268 NCollection_Mat4<T>& theWorldView,
269 const Standard_Integer theViewportWidth,
270 const Standard_Integer theViewportHeight) const;
71d8ccc7 271
778cd667 272private:
273
274 //! 3D anchor point for zoom/rotate transformation persistence.
275 struct PersParams3d
71d8ccc7 276 {
778cd667 277 Standard_Real PntX;
278 Standard_Real PntY;
279 Standard_Real PntZ;
280 };
281
282 //! 2d/trihedron transformation persistence parameters.
283 struct PersParams2d
284 {
285 Standard_Integer OffsetX;
286 Standard_Integer OffsetY;
287 Aspect_TypeOfTriedronPosition Corner;
288 };
289
290private:
291
292 Graphic3d_TransModeFlags myMode; //!< Transformation persistence mode flags
293 union
294 {
295 PersParams3d Params3d;
296 PersParams2d Params2d;
297 } myParams;
71d8ccc7 298
825aa485 299};
300
301// =======================================================================
302// function : Apply
303// purpose : Apply transformation to world view and projection matrices.
304// =======================================================================
305template<class T>
3fe9ce0e 306void Graphic3d_TransformPers::Apply (const Handle(Graphic3d_Camera)& theCamera,
778cd667 307 const NCollection_Mat4<T>& theProjection,
825aa485 308 NCollection_Mat4<T>& theWorldView,
309 const Standard_Integer theViewportWidth,
310 const Standard_Integer theViewportHeight) const
311{
150ed3d5 312 (void )theViewportWidth;
778cd667 313 (void )theProjection;
314 if (myMode == Graphic3d_TMF_None
71d8ccc7 315 || theViewportHeight == 0)
825aa485 316 {
317 return;
318 }
319
778cd667 320 // use total size when tiling is active
3bffef55 321 const Standard_Integer aVPSizeY = theCamera->Tile().IsValid() ? theCamera->Tile().TotalSize.y() : theViewportHeight;
778cd667 322
323 // a small enough jitter compensation offset
324 // to avoid image dragging within single pixel in corner cases
325 const Standard_Real aJitterComp = 0.001;
326 if (myMode == Graphic3d_TMF_TriedronPers)
3fe9ce0e 327 {
328 // reset Z focus for trihedron persistence
329 const Standard_Real aFocus = theCamera->IsOrthographic()
330 ? theCamera->Distance()
331 : (theCamera->ZFocusType() == Graphic3d_Camera::FocusType_Relative
332 ? Standard_Real(theCamera->ZFocus() * theCamera->Distance())
333 : Standard_Real(theCamera->ZFocus()));
334
335 // scale factor to pixels
336 const gp_XYZ aViewDim = theCamera->ViewDimensions (aFocus);
3bffef55 337 const Standard_Real aScale = Abs(aViewDim.Y()) / Standard_Real(aVPSizeY);
3fe9ce0e 338 const gp_Dir aForward (theCamera->Center().XYZ() - theCamera->Eye().XYZ());
339 gp_XYZ aCenter = theCamera->Center().XYZ() + aForward.XYZ() * (aFocus - theCamera->Distance());
778cd667 340 if ((myParams.Params2d.Corner & (Aspect_TOTP_LEFT | Aspect_TOTP_RIGHT)) != 0)
3fe9ce0e 341 {
778cd667 342 const Standard_Real anOffsetX = (Standard_Real(myParams.Params2d.OffsetX) + aJitterComp) * aScale;
343 const gp_Dir aSide = aForward.Crossed (theCamera->Up());
344 const gp_XYZ aDeltaX = aSide.XYZ() * (Abs(aViewDim.X()) * 0.5 - anOffsetX);
345 if ((myParams.Params2d.Corner & Aspect_TOTP_RIGHT) != 0)
3fe9ce0e 346 {
778cd667 347 aCenter += aDeltaX;
3fe9ce0e 348 }
349 else
350 {
778cd667 351 aCenter -= aDeltaX;
3fe9ce0e 352 }
353 }
778cd667 354 if ((myParams.Params2d.Corner & (Aspect_TOTP_TOP | Aspect_TOTP_BOTTOM)) != 0)
3fe9ce0e 355 {
778cd667 356 const Standard_Real anOffsetY = (Standard_Real(myParams.Params2d.OffsetY) + aJitterComp) * aScale;
357 const gp_XYZ aDeltaY = theCamera->Up().XYZ() * (Abs(aViewDim.Y()) * 0.5 - anOffsetY);
358 if ((myParams.Params2d.Corner & Aspect_TOTP_TOP) != 0)
3fe9ce0e 359 {
778cd667 360 aCenter += aDeltaY;
3fe9ce0e 361 }
362 else
363 {
778cd667 364 aCenter -= aDeltaY;
3fe9ce0e 365 }
366 }
367
778cd667 368 NCollection_Mat4<Standard_Real> aWorldView = theCamera->OrientationMatrix();
369 Graphic3d_TransformUtils::Translate (aWorldView, aCenter.X(), aCenter.Y(), aCenter.Z());
370 Graphic3d_TransformUtils::Scale (aWorldView, aScale, aScale, aScale);
371 theWorldView.ConvertFrom (aWorldView);
3fe9ce0e 372 return;
373 }
778cd667 374 else if (myMode == Graphic3d_TMF_2d)
825aa485 375 {
150ed3d5 376 const Standard_Real aFocus = theCamera->IsOrthographic()
377 ? theCamera->Distance()
378 : (theCamera->ZFocusType() == Graphic3d_Camera::FocusType_Relative
379 ? Standard_Real(theCamera->ZFocus() * theCamera->Distance())
380 : Standard_Real(theCamera->ZFocus()));
381
382 // scale factor to pixels
383 const gp_XYZ aViewDim = theCamera->ViewDimensions (aFocus);
3bffef55 384 const Standard_Real aScale = Abs(aViewDim.Y()) / Standard_Real(aVPSizeY);
150ed3d5 385 gp_XYZ aCenter (0.0, 0.0, -aFocus);
778cd667 386 if ((myParams.Params2d.Corner & (Aspect_TOTP_LEFT | Aspect_TOTP_RIGHT)) != 0)
825aa485 387 {
778cd667 388 aCenter.SetX (-aViewDim.X() * 0.5 + (Standard_Real(myParams.Params2d.OffsetX) + aJitterComp) * aScale);
389 if ((myParams.Params2d.Corner & Aspect_TOTP_RIGHT) != 0)
150ed3d5 390 {
391 aCenter.SetX (-aCenter.X());
392 }
825aa485 393 }
778cd667 394 if ((myParams.Params2d.Corner & (Aspect_TOTP_TOP | Aspect_TOTP_BOTTOM)) != 0)
825aa485 395 {
778cd667 396 aCenter.SetY (-aViewDim.Y() * 0.5 + (Standard_Real(myParams.Params2d.OffsetY) + aJitterComp) * aScale);
397 if ((myParams.Params2d.Corner & Aspect_TOTP_TOP) != 0)
150ed3d5 398 {
399 aCenter.SetY (-aCenter.Y());
400 }
825aa485 401 }
402
825aa485 403 theWorldView.InitIdentity();
150ed3d5 404 Graphic3d_TransformUtils::Translate (theWorldView, T(aCenter.X()), T(aCenter.Y()), T(aCenter.Z()));
405 Graphic3d_TransformUtils::Scale (theWorldView, T(aScale), T(aScale), T(aScale));
406 return;
825aa485 407 }
778cd667 408 else
825aa485 409 {
410 // Compute reference point for transformation in untransformed projection space.
7c3ef2f7 411 NCollection_Mat4<Standard_Real> aWorldView = theCamera->OrientationMatrix();
412 Graphic3d_TransformUtils::Translate (aWorldView, myParams.Params3d.PntX, myParams.Params3d.PntY, myParams.Params3d.PntZ);
778cd667 413 if ((myMode & Graphic3d_TMF_RotatePers) != 0)
825aa485 414 {
778cd667 415 // lock rotation by nullifying rotation component
7c3ef2f7 416 aWorldView.SetValue (0, 0, 1.0);
417 aWorldView.SetValue (1, 0, 0.0);
418 aWorldView.SetValue (2, 0, 0.0);
778cd667 419
7c3ef2f7 420 aWorldView.SetValue (0, 1, 0.0);
421 aWorldView.SetValue (1, 1, 1.0);
422 aWorldView.SetValue (2, 1, 0.0);
778cd667 423
7c3ef2f7 424 aWorldView.SetValue (0, 2, 0.0);
425 aWorldView.SetValue (1, 2, 0.0);
426 aWorldView.SetValue (2, 2, 1.0);
825aa485 427 }
428
778cd667 429 if ((myMode & Graphic3d_TMF_ZoomPers) != 0)
825aa485 430 {
778cd667 431 // lock zooming
432 gp_Vec aVecToEye (theCamera->Direction());
433 gp_Vec aVecToObj (theCamera->Eye(), gp_Pnt (myParams.Params3d.PntX, myParams.Params3d.PntY, myParams.Params3d.PntZ));
434 const Standard_Real aFocus = aVecToObj.Dot (aVecToEye);
435 const gp_XYZ aViewDim = theCamera->ViewDimensions (aFocus);
436 const Standard_Real aScale = Abs(aViewDim.Y()) / Standard_Real(aVPSizeY);
7c3ef2f7 437 Graphic3d_TransformUtils::Scale (aWorldView, aScale, aScale, aScale);
825aa485 438 }
7c3ef2f7 439 theWorldView.ConvertFrom (aWorldView);
778cd667 440 return;
825aa485 441 }
442}
443
444// =======================================================================
445// function : Apply
446// purpose : Apply transformation to bounding box of presentation.
447// =======================================================================
448template<class T>
3fe9ce0e 449void Graphic3d_TransformPers::Apply (const Handle(Graphic3d_Camera)& theCamera,
450 const NCollection_Mat4<T>& theProjection,
825aa485 451 const NCollection_Mat4<T>& theWorldView,
452 const Standard_Integer theViewportWidth,
453 const Standard_Integer theViewportHeight,
454 Bnd_Box& theBoundingBox) const
455{
3fe9ce0e 456 if (theBoundingBox.IsVoid())
457 {
458 return;
459 }
460
825aa485 461 T aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
462
463 theBoundingBox.Get (aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
464
7c3ef2f7 465 typename BVH_Box<T, 3>::BVH_VecNt aMin (aXmin, aYmin, aZmin);
466 typename BVH_Box<T, 3>::BVH_VecNt aMax (aXmax, aYmax, aZmax);
467 BVH_Box<T, 3> aBBox (aMin, aMax);
825aa485 468
3fe9ce0e 469 Apply (theCamera, theProjection, theWorldView, theViewportWidth, theViewportHeight, aBBox);
825aa485 470
471 theBoundingBox = Bnd_Box();
472 theBoundingBox.Update (aBBox.CornerMin().x(), aBBox.CornerMin().y(), aBBox.CornerMin().z(),
473 aBBox.CornerMax().x(), aBBox.CornerMax().y(), aBBox.CornerMax().z());
474}
475
476// =======================================================================
477// function : Apply
478// purpose : Apply transformation to bounding box of presentation.
479// =======================================================================
480template<class T>
3fe9ce0e 481void Graphic3d_TransformPers::Apply (const Handle(Graphic3d_Camera)& theCamera,
482 const NCollection_Mat4<T>& theProjection,
825aa485 483 const NCollection_Mat4<T>& theWorldView,
484 const Standard_Integer theViewportWidth,
485 const Standard_Integer theViewportHeight,
7c3ef2f7 486 BVH_Box<T, 3>& theBoundingBox) const
825aa485 487{
3fe9ce0e 488 NCollection_Mat4<T> aTPers = Compute (theCamera, theProjection, theWorldView, theViewportWidth, theViewportHeight);
489 if (aTPers.IsIdentity()
490 || !theBoundingBox.IsValid())
825aa485 491 {
492 return;
493 }
494
7c3ef2f7 495 const typename BVH_Box<T, 3>::BVH_VecNt& aMin = theBoundingBox.CornerMin();
496 const typename BVH_Box<T, 3>::BVH_VecNt& aMax = theBoundingBox.CornerMax();
825aa485 497
498 typename BVH_Box<T, 4>::BVH_VecNt anArrayOfCorners[8];
499 anArrayOfCorners[0] = typename BVH_Box<T, 4>::BVH_VecNt (aMin.x(), aMin.y(), aMin.z(), static_cast<T> (1.0));
500 anArrayOfCorners[1] = typename BVH_Box<T, 4>::BVH_VecNt (aMin.x(), aMin.y(), aMax.z(), static_cast<T> (1.0));
501 anArrayOfCorners[2] = typename BVH_Box<T, 4>::BVH_VecNt (aMin.x(), aMax.y(), aMin.z(), static_cast<T> (1.0));
502 anArrayOfCorners[3] = typename BVH_Box<T, 4>::BVH_VecNt (aMin.x(), aMax.y(), aMax.z(), static_cast<T> (1.0));
503 anArrayOfCorners[4] = typename BVH_Box<T, 4>::BVH_VecNt (aMax.x(), aMin.y(), aMin.z(), static_cast<T> (1.0));
504 anArrayOfCorners[5] = typename BVH_Box<T, 4>::BVH_VecNt (aMax.x(), aMin.y(), aMax.z(), static_cast<T> (1.0));
505 anArrayOfCorners[6] = typename BVH_Box<T, 4>::BVH_VecNt (aMax.x(), aMax.y(), aMin.z(), static_cast<T> (1.0));
506 anArrayOfCorners[7] = typename BVH_Box<T, 4>::BVH_VecNt (aMax.x(), aMax.y(), aMax.z(), static_cast<T> (1.0));
507
508 theBoundingBox.Clear();
509 for (Standard_Integer anIt = 0; anIt < 8; ++anIt)
510 {
511 typename BVH_Box<T, 4>::BVH_VecNt& aCorner = anArrayOfCorners[anIt];
512 aCorner = aTPers * aCorner;
513 aCorner /= aCorner.w();
7c3ef2f7 514 theBoundingBox.Add (aCorner.xyz());
825aa485 515 }
516}
517
518// =======================================================================
519// function : Compute
520// purpose : Compute transformation.
521// =======================================================================
522template<class T>
3fe9ce0e 523NCollection_Mat4<T> Graphic3d_TransformPers::Compute (const Handle(Graphic3d_Camera)& theCamera,
524 const NCollection_Mat4<T>& theProjection,
825aa485 525 const NCollection_Mat4<T>& theWorldView,
526 const Standard_Integer theViewportWidth,
527 const Standard_Integer theViewportHeight) const
528{
778cd667 529 if (myMode == Graphic3d_TMF_None)
825aa485 530 {
531 return NCollection_Mat4<T>();
532 }
533
778cd667 534 NCollection_Mat4<T> aWorldView (theWorldView);
825aa485 535 NCollection_Mat4<T> anUnviewMat;
71d8ccc7 536 if (!theWorldView.Inverted (anUnviewMat))
825aa485 537 {
538 return NCollection_Mat4<T>();
539 }
540
71d8ccc7 541 // compute only world-view matrix difference to avoid floating point instability
542 // caused by projection matrix modifications outside of this algorithm (e.g. by Z-fit)
778cd667 543 Apply (theCamera, theProjection, aWorldView, theViewportWidth, theViewportHeight);
71d8ccc7 544 return anUnviewMat * aWorldView;
825aa485 545}
546
547#endif // _Graphic3d_TransformPers_HeaderFile