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