0026413: Visualization, SelectMgr_ViewerSelector - Pixel tolerance is overridden...
[occt.git] / src / Graphic3d / Graphic3d_Camera.cxx
CommitLineData
b5ac8292 1// Created on: 2013-05-29
2// Created by: Anton POLETAEV
3// Copyright (c) 1999-2014 OPEN CASCADE SAS
4//
5// This file is part of Open CASCADE Technology software library.
6//
d5f74e42 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
b5ac8292 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#include <gp_Pln.hxx>
17#include <Standard_ShortReal.hxx>
18
19#include <Graphic3d_Vec4.hxx>
20#include <Graphic3d_Camera.hxx>
21
22#include <Standard_Atomic.hxx>
197ac94e 23#include <Standard_Assert.hxx>
b5ac8292 24
ed063270 25#include <NCollection_Sequence.hxx>
26
b5ac8292 27
28namespace
29{
30 // (degrees -> radians) * 0.5
197ac94e 31 static const Standard_Real DTR_HALF = 0.5 * 0.0174532925;
32
33 // default property values
34 static const Standard_Real DEFAULT_ZNEAR = 0.001;
35 static const Standard_Real DEFAULT_ZFAR = 3000.0;
b5ac8292 36
37 // atomic state counter
38 static volatile Standard_Integer THE_STATE_COUNTER = 0;
3c648527 39
40 // minimum camera distance
41 static const Standard_Real MIN_DISTANCE = Pow (0.1, ShortRealDigits() - 2);
ea764884 42
43 // z-range tolerance compatible with for floating point.
44 static Standard_Real zEpsilon()
45 {
46 return FLT_EPSILON;
47 }
48
49 // relative z-range tolerance compatible with for floating point.
50 static Standard_Real zEpsilon (const Standard_Real theValue)
51 {
9e3ca93a 52 if (theValue == 0)
53 {
54 return FLT_EPSILON;
55 }
ea764884 56 Standard_Real aLogRadix = Log10 (Abs (theValue)) / Log10 (FLT_RADIX);
57 Standard_Real aExp = Floor (aLogRadix);
58 return FLT_EPSILON * Pow (FLT_RADIX, aExp);
59 };
b5ac8292 60};
61
62// =======================================================================
63// function : Graphic3d_Camera
64// purpose :
65// =======================================================================
66Graphic3d_Camera::Graphic3d_Camera()
67: myUp (0.0, 1.0, 0.0),
68 myEye (0.0, 0.0, -1500.0),
69 myCenter (0.0, 0.0, 0.0),
b5ac8292 70 myAxialScale (1.0, 1.0, 1.0),
71 myProjType (Projection_Orthographic),
72 myFOVy (45.0),
197ac94e 73 myZNear (DEFAULT_ZNEAR),
74 myZFar (DEFAULT_ZFAR),
b5ac8292 75 myAspect (1.0),
76 myScale (1000.0),
77 myZFocus (1.0),
78 myZFocusType (FocusType_Relative),
79 myIOD (0.05),
197ac94e 80 myIODType (IODType_Relative)
b5ac8292 81{
82 myProjectionState = (Standard_Size)Standard_Atomic_Increment (&THE_STATE_COUNTER);
83 myOrientationState = (Standard_Size)Standard_Atomic_Increment (&THE_STATE_COUNTER);
b5ac8292 84}
85
86// =======================================================================
87// function : Graphic3d_Camera
88// purpose :
89// =======================================================================
90Graphic3d_Camera::Graphic3d_Camera (const Handle(Graphic3d_Camera)& theOther)
b5ac8292 91{
92 Copy (theOther);
93}
94
95// =======================================================================
96// function : CopyMappingData
97// purpose :
98// =======================================================================
99void Graphic3d_Camera::CopyMappingData (const Handle(Graphic3d_Camera)& theOtherCamera)
100{
197ac94e 101 myFOVy = theOtherCamera->myFOVy;
102 myZNear = theOtherCamera->myZNear;
103 myZFar = theOtherCamera->myZFar;
104 myAspect = theOtherCamera->myAspect;
105 myScale = theOtherCamera->myScale;
106 myZFocus = theOtherCamera->myZFocus;
107 myZFocusType = theOtherCamera->myZFocusType;
108 myIOD = theOtherCamera->myIOD;
109 myIODType = theOtherCamera->myIODType;
110 myProjType = theOtherCamera->myProjType;
111 myProjectionState = theOtherCamera->myProjectionState;
b5ac8292 112
197ac94e 113 InvalidateProjection();
b5ac8292 114}
115
116// =======================================================================
117// function : CopyOrientationData
118// purpose :
119// =======================================================================
120void Graphic3d_Camera::CopyOrientationData (const Handle(Graphic3d_Camera)& theOtherCamera)
121{
197ac94e 122 myUp = theOtherCamera->myUp;
123 myEye = theOtherCamera->myEye;
124 myCenter = theOtherCamera->myCenter;
125 myAxialScale = theOtherCamera->myAxialScale;
b5ac8292 126 myOrientationState = theOtherCamera->myOrientationState;
127
197ac94e 128 InvalidateOrientation();
b5ac8292 129}
130
131// =======================================================================
132// function : Copy
133// purpose :
134// =======================================================================
135void Graphic3d_Camera::Copy (const Handle(Graphic3d_Camera)& theOther)
136{
b5ac8292 137 CopyMappingData (theOther);
138 CopyOrientationData (theOther);
b5ac8292 139}
140
141// =======================================================================
142// function : SetEye
143// purpose :
144// =======================================================================
145void Graphic3d_Camera::SetEye (const gp_Pnt& theEye)
146{
147 myEye = theEye;
197ac94e 148 InvalidateOrientation();
b5ac8292 149}
150
151// =======================================================================
152// function : SetCenter
153// purpose :
154// =======================================================================
155void Graphic3d_Camera::SetCenter (const gp_Pnt& theCenter)
156{
157 myCenter = theCenter;
197ac94e 158 InvalidateOrientation();
b5ac8292 159}
160
161// =======================================================================
162// function : SetUp
163// purpose :
164// =======================================================================
165void Graphic3d_Camera::SetUp (const gp_Dir& theUp)
166{
167 myUp = theUp;
197ac94e 168 InvalidateOrientation();
b5ac8292 169}
170
171// =======================================================================
172// function : SetAxialScale
173// purpose :
174// =======================================================================
197ac94e 175void Graphic3d_Camera::SetAxialScale (const gp_XYZ& theAxialScale)
b5ac8292 176{
177 myAxialScale = theAxialScale;
197ac94e 178 InvalidateOrientation();
b5ac8292 179}
180
181// =======================================================================
182// function : SetDistance
183// purpose :
184// =======================================================================
185void Graphic3d_Camera::SetDistance (const Standard_Real theDistance)
186{
187 gp_Vec aCenter2Eye (Direction());
188 aCenter2Eye.Reverse();
3c648527 189
190 // Camera should have non-zero distance.
191 aCenter2Eye.Scale (Max (theDistance, MIN_DISTANCE));
b5ac8292 192 SetEye (Center().Translated (aCenter2Eye));
193}
194
195// =======================================================================
196// function : Distance
197// purpose :
198// =======================================================================
199Standard_Real Graphic3d_Camera::Distance() const
200{
201 return myEye.Distance (myCenter);
202}
203
204// =======================================================================
205// function : SetDirection
206// purpose :
207// =======================================================================
208void Graphic3d_Camera::SetDirection (const gp_Dir& theDir)
209{
210 gp_Vec aScaledDir (theDir);
211 aScaledDir.Scale (Distance());
212 aScaledDir.Reverse();
213 SetEye (Center().Translated (aScaledDir));
214}
215
216// =======================================================================
217// function : Direction
218// purpose :
219// =======================================================================
220gp_Dir Graphic3d_Camera::Direction() const
221{
222 return gp_Dir (gp_Vec (myEye, myCenter));
223}
224
225// =======================================================================
226// function : SetScale
227// purpose :
228// =======================================================================
229void Graphic3d_Camera::SetScale (const Standard_Real theScale)
230{
231 myScale = theScale;
232
233 switch (myProjType)
234 {
235 case Projection_Perspective :
236 case Projection_Stereo :
237 case Projection_MonoLeftEye :
238 case Projection_MonoRightEye :
239 {
240 Standard_Real aDistance = theScale * 0.5 / Tan(myFOVy * M_PI / 360.0);
241 SetDistance (aDistance);
242 }
243
244 default :
245 break;
246 }
247
197ac94e 248 InvalidateProjection();
b5ac8292 249}
250
251// =======================================================================
252// function : Scale
253// purpose :
254// =======================================================================
255Standard_Real Graphic3d_Camera::Scale() const
256{
257 switch (myProjType)
258 {
259 case Projection_Orthographic :
260 return myScale;
261
262 // case Projection_Perspective :
263 // case Projection_Stereo :
264 // case Projection_MonoLeftEye :
265 // case Projection_MonoRightEye :
266 default :
197ac94e 267 return Distance() * 2.0 * Tan (myFOVy * M_PI / 360.0);
b5ac8292 268 }
269}
270
271// =======================================================================
272// function : SetProjectionType
273// purpose :
274// =======================================================================
275void Graphic3d_Camera::SetProjectionType (const Projection theProjectionType)
276{
277 Projection anOldType = myProjType;
278
279 if (anOldType == theProjectionType)
280 {
281 return;
282 }
283
197ac94e 284 if (anOldType == Projection_Orthographic)
b5ac8292 285 {
197ac94e 286 if (myZNear <= RealEpsilon())
287 {
288 myZNear = DEFAULT_ZNEAR;
289 }
290 if (myZFar <= RealEpsilon())
291 {
292 myZFar = DEFAULT_ZFAR;
293 }
b5ac8292 294 }
295
197ac94e 296 myProjType = theProjectionType;
297
298 InvalidateProjection();
b5ac8292 299}
300
301// =======================================================================
302// function : SetFOVy
303// purpose :
304// =======================================================================
305void Graphic3d_Camera::SetFOVy (const Standard_Real theFOVy)
306{
307 myFOVy = theFOVy;
197ac94e 308 InvalidateProjection();
b5ac8292 309}
310
311// =======================================================================
197ac94e 312// function : SetZRange
b5ac8292 313// purpose :
314// =======================================================================
197ac94e 315void Graphic3d_Camera::SetZRange (const Standard_Real theZNear,
316 const Standard_Real theZFar)
b5ac8292 317{
197ac94e 318 Standard_ASSERT_RAISE (theZFar > theZNear, "ZFar should be greater than ZNear");
319 if (!IsOrthographic())
b5ac8292 320 {
197ac94e 321 Standard_ASSERT_RAISE (theZNear > 0.0, "Only positive Z-Near is allowed for perspective camera");
322 Standard_ASSERT_RAISE (theZFar > 0.0, "Only positive Z-Far is allowed for perspective camera");
b5ac8292 323 }
324
197ac94e 325 myZNear = theZNear;
326 myZFar = theZFar;
b5ac8292 327
197ac94e 328 InvalidateProjection();
b5ac8292 329}
330
331// =======================================================================
332// function : SetAspect
333// purpose :
334// =======================================================================
335void Graphic3d_Camera::SetAspect (const Standard_Real theAspect)
336{
337 myAspect = theAspect;
197ac94e 338 InvalidateProjection();
b5ac8292 339}
340
341// =======================================================================
342// function : SetZFocus
343// purpose :
344// =======================================================================
345void Graphic3d_Camera::SetZFocus(const FocusType theType, const Standard_Real theZFocus)
346{
347 myZFocusType = theType;
348 myZFocus = theZFocus;
197ac94e 349 InvalidateProjection();
b5ac8292 350}
351
352// =======================================================================
353// function : SetIOD
354// purpose :
355// =======================================================================
356void Graphic3d_Camera::SetIOD (const IODType theType, const Standard_Real theIOD)
357{
358 myIODType = theType;
359 myIOD = theIOD;
197ac94e 360 InvalidateProjection();
b5ac8292 361}
362
363// =======================================================================
364// function : OrthogonalizeUp
365// purpose :
366// =======================================================================
367void Graphic3d_Camera::OrthogonalizeUp()
368{
197ac94e 369 SetUp (OrthogonalizedUp());
b5ac8292 370}
371
372// =======================================================================
197ac94e 373// function : OrthogonalizedUp
b5ac8292 374// purpose :
375// =======================================================================
197ac94e 376gp_Dir Graphic3d_Camera::OrthogonalizedUp() const
b5ac8292 377{
197ac94e 378 gp_Dir aDir = Direction();
379 gp_Dir aLeft = aDir.Crossed (Up());
b5ac8292 380
197ac94e 381 // recompute up as: up = left x direction
382 return aLeft.Crossed (aDir);
b5ac8292 383}
384
385// =======================================================================
386// function : Transform
387// purpose :
388// =======================================================================
389void Graphic3d_Camera::Transform (const gp_Trsf& theTrsf)
390{
391 myUp.Transform (theTrsf);
392 myEye.Transform (theTrsf);
393 myCenter.Transform (theTrsf);
197ac94e 394 InvalidateOrientation();
b5ac8292 395}
396
397// =======================================================================
398// function : safePointCast
399// purpose :
400// =======================================================================
197ac94e 401static Graphic3d_Vec4d safePointCast (const gp_Pnt& thePnt)
b5ac8292 402{
403 Standard_Real aLim = 1e15f;
197ac94e 404
b5ac8292 405 // have to deal with values greater then max float
406 gp_Pnt aSafePoint = thePnt;
407 const Standard_Real aBigFloat = aLim * 0.1f;
408 if (Abs (aSafePoint.X()) > aLim)
409 aSafePoint.SetX (aSafePoint.X() >= 0 ? aBigFloat : -aBigFloat);
410 if (Abs (aSafePoint.Y()) > aLim)
411 aSafePoint.SetY (aSafePoint.Y() >= 0 ? aBigFloat : -aBigFloat);
412 if (Abs (aSafePoint.Z()) > aLim)
413 aSafePoint.SetZ (aSafePoint.Z() >= 0 ? aBigFloat : -aBigFloat);
414
415 // convert point
197ac94e 416 Graphic3d_Vec4d aPnt (aSafePoint.X(), aSafePoint.Y(), aSafePoint.Z(), 1.0);
b5ac8292 417
418 return aPnt;
419}
420
421// =======================================================================
422// function : Project
423// purpose :
424// =======================================================================
425gp_Pnt Graphic3d_Camera::Project (const gp_Pnt& thePnt) const
426{
197ac94e 427 const Graphic3d_Mat4d& aViewMx = OrientationMatrix();
428 const Graphic3d_Mat4d& aProjMx = ProjectionMatrix();
b5ac8292 429
430 // use compatible type of point
197ac94e 431 Graphic3d_Vec4d aPnt = safePointCast (thePnt);
b5ac8292 432
433 aPnt = aViewMx * aPnt; // convert to view coordinate space
434 aPnt = aProjMx * aPnt; // convert to projection coordinate space
435
436 const Standard_Real aInvW = 1.0 / Standard_Real (aPnt.w());
437
438 return gp_Pnt (aPnt.x() * aInvW, aPnt.y() * aInvW, aPnt.z() * aInvW);
439}
440
441// =======================================================================
442// function : UnProject
443// purpose :
444// =======================================================================
445gp_Pnt Graphic3d_Camera::UnProject (const gp_Pnt& thePnt) const
446{
197ac94e 447 const Graphic3d_Mat4d& aViewMx = OrientationMatrix();
448 const Graphic3d_Mat4d& aProjMx = ProjectionMatrix();
b5ac8292 449
197ac94e 450 Graphic3d_Mat4d aInvView;
451 Graphic3d_Mat4d aInvProj;
b5ac8292 452
453 // this case should never happen
454 if (!aViewMx.Inverted (aInvView) || !aProjMx.Inverted (aInvProj))
455 {
456 return gp_Pnt (0.0, 0.0, 0.0);
457 }
458
459 // use compatible type of point
197ac94e 460 Graphic3d_Vec4d aPnt = safePointCast (thePnt);
b5ac8292 461
462 aPnt = aInvProj * aPnt; // convert to view coordinate space
463 aPnt = aInvView * aPnt; // convert to world coordinate space
464
465 const Standard_Real aInvW = 1.0 / Standard_Real (aPnt.w());
466
467 return gp_Pnt (aPnt.x() * aInvW, aPnt.y() * aInvW, aPnt.z() * aInvW);
468}
469
470// =======================================================================
471// function : ConvertView2Proj
472// purpose :
473// =======================================================================
474gp_Pnt Graphic3d_Camera::ConvertView2Proj (const gp_Pnt& thePnt) const
475{
197ac94e 476 const Graphic3d_Mat4d& aProjMx = ProjectionMatrix();
b5ac8292 477
478 // use compatible type of point
197ac94e 479 Graphic3d_Vec4d aPnt = safePointCast (thePnt);
b5ac8292 480
481 aPnt = aProjMx * aPnt; // convert to projection coordinate space
482
483 const Standard_Real aInvW = 1.0 / Standard_Real (aPnt.w());
484
485 return gp_Pnt (aPnt.x() * aInvW, aPnt.y() * aInvW, aPnt.z() * aInvW);
486}
487
488// =======================================================================
489// function : ConvertProj2View
490// purpose :
491// =======================================================================
492gp_Pnt Graphic3d_Camera::ConvertProj2View (const gp_Pnt& thePnt) const
493{
197ac94e 494 const Graphic3d_Mat4d& aProjMx = ProjectionMatrix();
b5ac8292 495
197ac94e 496 Graphic3d_Mat4d aInvProj;
b5ac8292 497
498 // this case should never happen, but...
499 if (!aProjMx.Inverted (aInvProj))
500 {
197ac94e 501 return gp_Pnt (0, 0, 0);
b5ac8292 502 }
503
504 // use compatible type of point
197ac94e 505 Graphic3d_Vec4d aPnt = safePointCast (thePnt);
b5ac8292 506
507 aPnt = aInvProj * aPnt; // convert to view coordinate space
508
509 const Standard_Real aInvW = 1.0 / Standard_Real (aPnt.w());
510
511 return gp_Pnt (aPnt.x() * aInvW, aPnt.y() * aInvW, aPnt.z() * aInvW);
512}
513
514// =======================================================================
515// function : ConvertWorld2View
516// purpose :
517// =======================================================================
518gp_Pnt Graphic3d_Camera::ConvertWorld2View (const gp_Pnt& thePnt) const
519{
197ac94e 520 const Graphic3d_Mat4d& aViewMx = OrientationMatrix();
b5ac8292 521
522 // use compatible type of point
197ac94e 523 Graphic3d_Vec4d aPnt = safePointCast (thePnt);
b5ac8292 524
525 aPnt = aViewMx * aPnt; // convert to view coordinate space
526
527 const Standard_Real aInvW = 1.0 / Standard_Real (aPnt.w());
528
529 return gp_Pnt (aPnt.x() * aInvW, aPnt.y() * aInvW, aPnt.z() * aInvW);
530}
531
532// =======================================================================
533// function : ConvertView2World
534// purpose :
535// =======================================================================
536gp_Pnt Graphic3d_Camera::ConvertView2World (const gp_Pnt& thePnt) const
537{
197ac94e 538 const Graphic3d_Mat4d& aViewMx = OrientationMatrix();
b5ac8292 539
197ac94e 540 Graphic3d_Mat4d aInvView;
b5ac8292 541
542 if (!aViewMx.Inverted (aInvView))
543 {
544 return gp_Pnt(0, 0, 0);
545 }
546
547 // use compatible type of point
197ac94e 548 Graphic3d_Vec4d aPnt = safePointCast (thePnt);
b5ac8292 549
550 aPnt = aInvView * aPnt; // convert to world coordinate space
551
552 const Standard_Real aInvW = 1.0 / Standard_Real (aPnt.w());
553
554 return gp_Pnt (aPnt.x() * aInvW, aPnt.y() * aInvW, aPnt.z() * aInvW);
555}
556
557// =======================================================================
558// function : ViewDimensions
559// purpose :
560// =======================================================================
197ac94e 561gp_XYZ Graphic3d_Camera::ViewDimensions() const
b5ac8292 562{
563 // view plane dimensions
539d3a1b 564 Standard_Real aSize = IsOrthographic() ? myScale : (2.0 * Distance() * Tan (DTR_HALF * myFOVy));
565 Standard_Real aSizeX, aSizeY;
566 if (myAspect > 1.0)
567 {
568 aSizeX = aSize * myAspect;
569 aSizeY = aSize;
570 }
571 else
572 {
573 aSizeX = aSize;
574 aSizeY = aSize / myAspect;
575 }
b5ac8292 576
577 // and frustum depth
197ac94e 578 return gp_XYZ (aSizeX, aSizeY, myZFar - myZNear);
b5ac8292 579}
580
581// =======================================================================
197ac94e 582// function : Frustum
b5ac8292 583// purpose :
584// =======================================================================
197ac94e 585void Graphic3d_Camera::Frustum (gp_Pln& theLeft,
586 gp_Pln& theRight,
587 gp_Pln& theBottom,
588 gp_Pln& theTop,
589 gp_Pln& theNear,
590 gp_Pln& theFar) const
b5ac8292 591{
197ac94e 592 gp_Vec aProjection = gp_Vec (Direction());
593 gp_Vec anUp = OrthogonalizedUp();
594 gp_Vec aSide = aProjection ^ anUp;
595
596 Standard_ASSERT_RAISE (
597 !aProjection.IsParallel (anUp, Precision::Angular()),
598 "Can not derive SIDE = PROJ x UP - directions are parallel");
599
600 theNear = gp_Pln (Eye().Translated (aProjection * ZNear()), aProjection);
601 theFar = gp_Pln (Eye().Translated (aProjection * ZFar()), -aProjection);
602
603 Standard_Real aHScaleHor = Scale() * 0.5 * Aspect();
604 Standard_Real aHScaleVer = Scale() * 0.5;
605
606 gp_Pnt aPntLeft = Center().Translated (aHScaleHor * -aSide);
607 gp_Pnt aPntRight = Center().Translated (aHScaleHor * aSide);
608 gp_Pnt aPntBottom = Center().Translated (aHScaleVer * -anUp);
609 gp_Pnt aPntTop = Center().Translated (aHScaleVer * anUp);
610
611 gp_Vec aDirLeft = aSide;
612 gp_Vec aDirRight = -aSide;
613 gp_Vec aDirBottom = anUp;
614 gp_Vec aDirTop = -anUp;
615 if (!IsOrthographic())
616 {
617 Standard_Real aHFOVHor = ATan (Tan (DTR_HALF * FOVy()) * Aspect());
618 Standard_Real aHFOVVer = DTR_HALF * FOVy();
619 aDirLeft.Rotate (gp_Ax1 (gp::Origin(), anUp), aHFOVHor);
620 aDirRight.Rotate (gp_Ax1 (gp::Origin(), anUp), -aHFOVHor);
621 aDirBottom.Rotate (gp_Ax1 (gp::Origin(), aSide), -aHFOVVer);
622 aDirTop.Rotate (gp_Ax1 (gp::Origin(), aSide), aHFOVVer);
623 }
624
625 theLeft = gp_Pln (aPntLeft, aDirLeft);
626 theRight = gp_Pln (aPntRight, aDirRight);
627 theBottom = gp_Pln (aPntBottom, aDirBottom);
628 theTop = gp_Pln (aPntTop, aDirTop);
629}
630
631// =======================================================================
632// function : OrientationMatrix
633// purpose :
634// =======================================================================
635const Graphic3d_Mat4d& Graphic3d_Camera::OrientationMatrix() const
636{
637 return *UpdateOrientation (myMatricesD).Orientation;
638}
639
640// =======================================================================
641// function : OrientationMatrixF
642// purpose :
643// =======================================================================
644const Graphic3d_Mat4& Graphic3d_Camera::OrientationMatrixF() const
645{
646 return *UpdateOrientation (myMatricesF).Orientation;
647}
648
649// =======================================================================
650// function : ProjectionMatrix
651// purpose :
652// =======================================================================
653const Graphic3d_Mat4d& Graphic3d_Camera::ProjectionMatrix() const
654{
655 return *UpdateProjection (myMatricesD).MProjection;
656}
657
658// =======================================================================
659// function : ProjectionMatrixF
660// purpose :
661// =======================================================================
662const Graphic3d_Mat4& Graphic3d_Camera::ProjectionMatrixF() const
663{
664 return *UpdateProjection (myMatricesF).MProjection;
665}
666
667// =======================================================================
668// function : ProjectionStereoLeft
669// purpose :
670// =======================================================================
671const Graphic3d_Mat4d& Graphic3d_Camera::ProjectionStereoLeft() const
672{
673 return *UpdateProjection (myMatricesD).LProjection;
674}
675
676// =======================================================================
677// function : ProjectionStereoLeftF
678// purpose :
679// =======================================================================
680const Graphic3d_Mat4& Graphic3d_Camera::ProjectionStereoLeftF() const
681{
682 return *UpdateProjection (myMatricesF).LProjection;
683}
684
685// =======================================================================
686// function : ProjectionStereoRight
687// purpose :
688// =======================================================================
689const Graphic3d_Mat4d& Graphic3d_Camera::ProjectionStereoRight() const
690{
691 return *UpdateProjection (myMatricesD).RProjection;
692}
693
694// =======================================================================
695// function : ProjectionStereoRightF
696// purpose :
697// =======================================================================
698const Graphic3d_Mat4& Graphic3d_Camera::ProjectionStereoRightF() const
699{
700 return *UpdateProjection (myMatricesF).RProjection;
b5ac8292 701}
702
703// =======================================================================
704// function : UpdateProjection
705// purpose :
706// =======================================================================
197ac94e 707template <typename Elem_t>
708Graphic3d_Camera::TransformMatrices<Elem_t>&
709 Graphic3d_Camera::UpdateProjection (TransformMatrices<Elem_t>& theMatrices) const
b5ac8292 710{
197ac94e 711 if (theMatrices.IsProjectionValid())
b5ac8292 712 {
197ac94e 713 return theMatrices; // for inline accessors
b5ac8292 714 }
715
197ac94e 716 theMatrices.InitProjection();
b5ac8292 717
718 // sets top of frustum based on FOVy and near clipping plane
197ac94e 719 Elem_t aScale = static_cast<Elem_t> (myScale);
720 Elem_t aZNear = static_cast<Elem_t> (myZNear);
721 Elem_t aZFar = static_cast<Elem_t> (myZFar);
722 Elem_t anAspect = static_cast<Elem_t> (myAspect);
ab1c121b 723 Elem_t aDXHalf = 0.0, aDYHalf = 0.0;
b5ac8292 724 if (IsOrthographic())
725 {
ab1c121b 726 aDXHalf = aScale * Elem_t (0.5);
197ac94e 727 aDYHalf = aScale * Elem_t (0.5);
b5ac8292 728 }
729 else
730 {
ab1c121b 731 aDXHalf = aZNear * Elem_t (Tan (DTR_HALF * myFOVy));
197ac94e 732 aDYHalf = aZNear * Elem_t (Tan (DTR_HALF * myFOVy));
b5ac8292 733 }
734
ab1c121b 735 if (anAspect > 1.0)
736 {
737 aDXHalf *= anAspect;
738 }
739 else
740 {
741 aDYHalf /= anAspect;
742 }
743
b5ac8292 744 // sets right of frustum based on aspect ratio
197ac94e 745 Elem_t aLeft = -aDXHalf;
746 Elem_t aRight = aDXHalf;
747 Elem_t aBot = -aDYHalf;
748 Elem_t aTop = aDYHalf;
b5ac8292 749
197ac94e 750 Elem_t aIOD = myIODType == IODType_Relative
751 ? static_cast<Elem_t> (myIOD * Distance())
752 : static_cast<Elem_t> (myIOD);
b5ac8292 753
197ac94e 754 Elem_t aFocus = myZFocusType == FocusType_Relative
755 ? static_cast<Elem_t> (myZFocus * Distance())
756 : static_cast<Elem_t> (myZFocus);
b5ac8292 757
758 switch (myProjType)
759 {
760 case Projection_Orthographic :
197ac94e 761 OrthoProj (aLeft, aRight, aBot, aTop, aZNear, aZFar, *theMatrices.MProjection);
b5ac8292 762 break;
763
764 case Projection_Perspective :
197ac94e 765 PerspectiveProj (aLeft, aRight, aBot, aTop, aZNear, aZFar, *theMatrices.MProjection);
b5ac8292 766 break;
767
768 case Projection_MonoLeftEye :
769 {
197ac94e 770 StereoEyeProj (aLeft, aRight, aBot, aTop,
771 aZNear, aZFar, aIOD, aFocus,
772 Standard_True, *theMatrices.MProjection);
38a0206f 773 *theMatrices.LProjection = *theMatrices.MProjection;
b5ac8292 774 break;
775 }
776
777 case Projection_MonoRightEye :
778 {
197ac94e 779 StereoEyeProj (aLeft, aRight, aBot, aTop,
780 aZNear, aZFar, aIOD, aFocus,
781 Standard_False, *theMatrices.MProjection);
38a0206f 782 *theMatrices.RProjection = *theMatrices.MProjection;
b5ac8292 783 break;
784 }
785
786 case Projection_Stereo :
787 {
197ac94e 788 PerspectiveProj (aLeft, aRight, aBot, aTop, aZNear, aZFar, *theMatrices.MProjection);
b5ac8292 789
197ac94e 790 StereoEyeProj (aLeft, aRight, aBot, aTop,
791 aZNear, aZFar, aIOD, aFocus,
792 Standard_True,
793 *theMatrices.LProjection);
b5ac8292 794
197ac94e 795 StereoEyeProj (aLeft, aRight, aBot, aTop,
796 aZNear, aZFar, aIOD, aFocus,
797 Standard_False,
798 *theMatrices.RProjection);
b5ac8292 799 break;
800 }
801 }
197ac94e 802
803 return theMatrices; // for inline accessors
b5ac8292 804}
805
806// =======================================================================
807// function : UpdateOrientation
808// purpose :
809// =======================================================================
197ac94e 810template <typename Elem_t>
811Graphic3d_Camera::TransformMatrices<Elem_t>&
812 Graphic3d_Camera::UpdateOrientation (TransformMatrices<Elem_t>& theMatrices) const
b5ac8292 813{
197ac94e 814 if (theMatrices.IsOrientationValid())
b5ac8292 815 {
197ac94e 816 return theMatrices; // for inline accessors
b5ac8292 817 }
818
197ac94e 819 theMatrices.InitOrientation();
820
821 NCollection_Vec3<Elem_t> anEye (static_cast<Elem_t> (myEye.X()),
822 static_cast<Elem_t> (myEye.Y()),
823 static_cast<Elem_t> (myEye.Z()));
824
825 NCollection_Vec3<Elem_t> aCenter (static_cast<Elem_t> (myCenter.X()),
826 static_cast<Elem_t> (myCenter.Y()),
827 static_cast<Elem_t> (myCenter.Z()));
b5ac8292 828
197ac94e 829 NCollection_Vec3<Elem_t> anUp (static_cast<Elem_t> (myUp.X()),
830 static_cast<Elem_t> (myUp.Y()),
831 static_cast<Elem_t> (myUp.Z()));
b5ac8292 832
197ac94e 833 NCollection_Vec3<Elem_t> anAxialScale (static_cast<Elem_t> (myAxialScale.X()),
834 static_cast<Elem_t> (myAxialScale.Y()),
835 static_cast<Elem_t> (myAxialScale.Z()));
b5ac8292 836
197ac94e 837 LookOrientation (anEye, aCenter, anUp, anAxialScale, *theMatrices.Orientation);
b5ac8292 838
197ac94e 839 return theMatrices; // for inline accessors
840}
b5ac8292 841
197ac94e 842// =======================================================================
843// function : InvalidateProjection
844// purpose :
845// =======================================================================
846void Graphic3d_Camera::InvalidateProjection()
847{
848 myMatricesD.ResetProjection();
849 myMatricesF.ResetProjection();
850 myProjectionState = (Standard_Size)Standard_Atomic_Increment (&THE_STATE_COUNTER);
851}
b5ac8292 852
197ac94e 853// =======================================================================
854// function : InvalidateOrientation
855// purpose :
856// =======================================================================
857void Graphic3d_Camera::InvalidateOrientation()
858{
859 myMatricesD.ResetOrientation();
860 myMatricesF.ResetOrientation();
861 myOrientationState = (Standard_Size)Standard_Atomic_Increment (&THE_STATE_COUNTER);
b5ac8292 862}
863
864// =======================================================================
865// function : OrthoProj
866// purpose :
867// =======================================================================
197ac94e 868template <typename Elem_t>
869void Graphic3d_Camera::OrthoProj (const Elem_t theLeft,
870 const Elem_t theRight,
871 const Elem_t theBottom,
872 const Elem_t theTop,
873 const Elem_t theNear,
874 const Elem_t theFar,
875 NCollection_Mat4<Elem_t>& theOutMx)
b5ac8292 876{
877 // row 0
197ac94e 878 theOutMx.ChangeValue (0, 0) = Elem_t (2.0) / (theRight - theLeft);
879 theOutMx.ChangeValue (0, 1) = Elem_t (0.0);
880 theOutMx.ChangeValue (0, 2) = Elem_t (0.0);
b5ac8292 881 theOutMx.ChangeValue (0, 3) = - (theRight + theLeft) / (theRight - theLeft);
882
883 // row 1
197ac94e 884 theOutMx.ChangeValue (1, 0) = Elem_t (0.0);
885 theOutMx.ChangeValue (1, 1) = Elem_t (2.0) / (theTop - theBottom);
886 theOutMx.ChangeValue (1, 2) = Elem_t (0.0);
b5ac8292 887 theOutMx.ChangeValue (1, 3) = - (theTop + theBottom) / (theTop - theBottom);
888
889 // row 2
197ac94e 890 theOutMx.ChangeValue (2, 0) = Elem_t (0.0);
891 theOutMx.ChangeValue (2, 1) = Elem_t (0.0);
892 theOutMx.ChangeValue (2, 2) = Elem_t (-2.0) / (theFar - theNear);
b5ac8292 893 theOutMx.ChangeValue (2, 3) = - (theFar + theNear) / (theFar - theNear);
894
895 // row 3
197ac94e 896 theOutMx.ChangeValue (3, 0) = Elem_t (0.0);
897 theOutMx.ChangeValue (3, 1) = Elem_t (0.0);
898 theOutMx.ChangeValue (3, 2) = Elem_t (0.0);
899 theOutMx.ChangeValue (3, 3) = Elem_t (1.0);
b5ac8292 900}
901
902// =======================================================================
903// function : PerspectiveProj
904// purpose :
905// =======================================================================
197ac94e 906template <typename Elem_t>
907void Graphic3d_Camera::PerspectiveProj (const Elem_t theLeft,
908 const Elem_t theRight,
909 const Elem_t theBottom,
910 const Elem_t theTop,
911 const Elem_t theNear,
912 const Elem_t theFar,
913 NCollection_Mat4<Elem_t>& theOutMx)
b5ac8292 914{
915 // column 0
197ac94e 916 theOutMx.ChangeValue (0, 0) = (Elem_t (2.0) * theNear) / (theRight - theLeft);
917 theOutMx.ChangeValue (1, 0) = Elem_t (0.0);
918 theOutMx.ChangeValue (2, 0) = Elem_t (0.0);
919 theOutMx.ChangeValue (3, 0) = Elem_t (0.0);
b5ac8292 920
921 // column 1
197ac94e 922 theOutMx.ChangeValue (0, 1) = Elem_t (0.0);
923 theOutMx.ChangeValue (1, 1) = (Elem_t (2.0) * theNear) / (theTop - theBottom);
924 theOutMx.ChangeValue (2, 1) = Elem_t (0.0);
925 theOutMx.ChangeValue (3, 1) = Elem_t (0.0);
b5ac8292 926
927 // column 2
928 theOutMx.ChangeValue (0, 2) = (theRight + theLeft) / (theRight - theLeft);
929 theOutMx.ChangeValue (1, 2) = (theTop + theBottom) / (theTop - theBottom);
930 theOutMx.ChangeValue (2, 2) = -(theFar + theNear) / (theFar - theNear);
197ac94e 931 theOutMx.ChangeValue (3, 2) = Elem_t (-1.0);
b5ac8292 932
933 // column 3
197ac94e 934 theOutMx.ChangeValue (0, 3) = Elem_t (0.0);
935 theOutMx.ChangeValue (1, 3) = Elem_t (0.0);
936 theOutMx.ChangeValue (2, 3) = -(Elem_t (2.0) * theFar * theNear) / (theFar - theNear);
937 theOutMx.ChangeValue (3, 3) = Elem_t (0.0);
b5ac8292 938}
939
940// =======================================================================
941// function : StereoEyeProj
942// purpose :
943// =======================================================================
197ac94e 944template <typename Elem_t>
945void Graphic3d_Camera::StereoEyeProj (const Elem_t theLeft,
946 const Elem_t theRight,
947 const Elem_t theBottom,
948 const Elem_t theTop,
949 const Elem_t theNear,
950 const Elem_t theFar,
951 const Elem_t theIOD,
952 const Elem_t theZFocus,
953 const Standard_Boolean theIsLeft,
954 NCollection_Mat4<Elem_t>& theOutMx)
b5ac8292 955{
197ac94e 956 Elem_t aDx = theIsLeft ? Elem_t (0.5) * theIOD : Elem_t (-0.5) * theIOD;
957 Elem_t aDXStereoShift = aDx * theNear / theZFocus;
b5ac8292 958
959 // construct eye projection matrix
960 PerspectiveProj (theLeft + aDXStereoShift,
961 theRight + aDXStereoShift,
962 theBottom, theTop, theNear, theFar,
b5ac8292 963 theOutMx);
964
197ac94e 965 if (theIOD != Elem_t (0.0))
b5ac8292 966 {
967 // X translation to cancel parallax
197ac94e 968 theOutMx.Translate (NCollection_Vec3<Elem_t> (aDx, Elem_t (0.0), Elem_t (0.0)));
b5ac8292 969 }
970}
971
972// =======================================================================
973// function : LookOrientation
974// purpose :
975// =======================================================================
197ac94e 976template <typename Elem_t>
977void Graphic3d_Camera::LookOrientation (const NCollection_Vec3<Elem_t>& theEye,
978 const NCollection_Vec3<Elem_t>& theLookAt,
979 const NCollection_Vec3<Elem_t>& theUpDir,
980 const NCollection_Vec3<Elem_t>& theAxialScale,
981 NCollection_Mat4<Elem_t>& theOutMx)
b5ac8292 982{
197ac94e 983 NCollection_Vec3<Elem_t> aForward = theLookAt - theEye;
b5ac8292 984 aForward.Normalize();
985
986 // side = forward x up
197ac94e 987 NCollection_Vec3<Elem_t> aSide = NCollection_Vec3<Elem_t>::Cross (aForward, theUpDir);
b5ac8292 988 aSide.Normalize();
989
990 // recompute up as: up = side x forward
197ac94e 991 NCollection_Vec3<Elem_t> anUp = NCollection_Vec3<Elem_t>::Cross (aSide, aForward);
b5ac8292 992
197ac94e 993 NCollection_Mat4<Elem_t> aLookMx;
b5ac8292 994 aLookMx.SetRow (0, aSide);
995 aLookMx.SetRow (1, anUp);
996 aLookMx.SetRow (2, -aForward);
997
197ac94e 998 theOutMx.InitIdentity();
999 theOutMx.Multiply (aLookMx);
b5ac8292 1000 theOutMx.Translate (-theEye);
1001
197ac94e 1002 NCollection_Mat4<Elem_t> anAxialScaleMx;
b5ac8292 1003 anAxialScaleMx.ChangeValue (0, 0) = theAxialScale.x();
1004 anAxialScaleMx.ChangeValue (1, 1) = theAxialScale.y();
1005 anAxialScaleMx.ChangeValue (2, 2) = theAxialScale.z();
1006
1007 theOutMx.Multiply (anAxialScaleMx);
1008}
6bc6a6fc 1009
1010//=============================================================================
1011//function : ZFitAll
1012//purpose :
1013//=============================================================================
1014void Graphic3d_Camera::ZFitAll (const Standard_Real theScaleFactor, const Bnd_Box& theMinMax, const Bnd_Box& theGraphicBB)
1015{
1016 Standard_ASSERT_RAISE (theScaleFactor > 0.0, "Zero or negative scale factor is not allowed.");
1017
ea764884 1018 // Method changes zNear and zFar parameters of camera so as to fit graphical structures
1019 // by their graphical boundaries. It precisely fits min max boundaries of primary application
1020 // objects (second argument), while it can sacrifice the real graphical boundaries of the
1021 // scene with infinite or helper objects (third argument) for the sake of perspective projection.
ed063270 1022 if (theGraphicBB.IsVoid())
6bc6a6fc 1023 {
ea764884 1024 SetZRange (DEFAULT_ZNEAR, DEFAULT_ZFAR);
6bc6a6fc 1025 return;
1026 }
1027
ea764884 1028 // Measure depth of boundary points from camera eye.
ed063270 1029 NCollection_Sequence<gp_Pnt> aPntsToMeasure;
1030
ea764884 1031 Standard_Real aGraphicBB[6];
ed063270 1032 theGraphicBB.Get (aGraphicBB[0], aGraphicBB[1], aGraphicBB[2], aGraphicBB[3], aGraphicBB[4], aGraphicBB[5]);
1033
1034 aPntsToMeasure.Append (gp_Pnt (aGraphicBB[0], aGraphicBB[1], aGraphicBB[2]));
1035 aPntsToMeasure.Append (gp_Pnt (aGraphicBB[0], aGraphicBB[1], aGraphicBB[5]));
1036 aPntsToMeasure.Append (gp_Pnt (aGraphicBB[0], aGraphicBB[4], aGraphicBB[2]));
1037 aPntsToMeasure.Append (gp_Pnt (aGraphicBB[0], aGraphicBB[4], aGraphicBB[5]));
1038 aPntsToMeasure.Append (gp_Pnt (aGraphicBB[3], aGraphicBB[1], aGraphicBB[2]));
1039 aPntsToMeasure.Append (gp_Pnt (aGraphicBB[3], aGraphicBB[1], aGraphicBB[5]));
1040 aPntsToMeasure.Append (gp_Pnt (aGraphicBB[3], aGraphicBB[4], aGraphicBB[2]));
1041 aPntsToMeasure.Append (gp_Pnt (aGraphicBB[3], aGraphicBB[4], aGraphicBB[5]));
1042
1043 if (!theMinMax.IsVoid() && !theMinMax.IsWhole())
6bc6a6fc 1044 {
ea764884 1045 Standard_Real aMinMax[6];
ed063270 1046 theMinMax.Get (aMinMax[0], aMinMax[1], aMinMax[2], aMinMax[3], aMinMax[4], aMinMax[5]);
1047
1048 aPntsToMeasure.Append (gp_Pnt (aMinMax[0], aMinMax[1], aMinMax[2]));
1049 aPntsToMeasure.Append (gp_Pnt (aMinMax[0], aMinMax[1], aMinMax[5]));
1050 aPntsToMeasure.Append (gp_Pnt (aMinMax[0], aMinMax[4], aMinMax[2]));
1051 aPntsToMeasure.Append (gp_Pnt (aMinMax[0], aMinMax[4], aMinMax[5]));
1052 aPntsToMeasure.Append (gp_Pnt (aMinMax[3], aMinMax[1], aMinMax[2]));
1053 aPntsToMeasure.Append (gp_Pnt (aMinMax[3], aMinMax[1], aMinMax[5]));
1054 aPntsToMeasure.Append (gp_Pnt (aMinMax[3], aMinMax[4], aMinMax[2]));
1055 aPntsToMeasure.Append (gp_Pnt (aMinMax[3], aMinMax[4], aMinMax[5]));
1056 }
6bc6a6fc 1057
ea764884 1058 // Camera eye plane.
6bc6a6fc 1059 gp_Dir aCamDir = Direction();
1060 gp_Pnt aCamEye = myEye;
1061 gp_Pln aCamPln (aCamEye, aCamDir);
1062
1063 Standard_Real aModelMinDist = RealLast();
1064 Standard_Real aModelMaxDist = RealFirst();
1065 Standard_Real aGraphicMinDist = RealLast();
1066 Standard_Real aGraphicMaxDist = RealFirst();
1067
1068 const gp_XYZ& anAxialScale = myAxialScale;
1069
ea764884 1070 // Get minimum and maximum distances to the eye plane.
ed063270 1071 Standard_Integer aCounter = 0;
1072 NCollection_Sequence<gp_Pnt>::Iterator aPntIt(aPntsToMeasure);
1073 for (; aPntIt.More(); aPntIt.Next())
6bc6a6fc 1074 {
ed063270 1075 gp_Pnt aMeasurePnt = aPntIt.Value();
6bc6a6fc 1076
1077 aMeasurePnt = gp_Pnt (aMeasurePnt.X() * anAxialScale.X(),
ed063270 1078 aMeasurePnt.Y() * anAxialScale.Y(),
1079 aMeasurePnt.Z() * anAxialScale.Z());
6bc6a6fc 1080
1081 Standard_Real aDistance = aCamPln.Distance (aMeasurePnt);
1082
ea764884 1083 // Check if the camera is intruded into the scene.
6bc6a6fc 1084 if (aCamDir.IsOpposite (gp_Vec (aCamEye, aMeasurePnt), M_PI * 0.5))
1085 {
1086 aDistance *= -1;
1087 }
1088
ea764884 1089 // The first eight points are from theGraphicBB, the last eight points are from theMinMax (can be absent).
ed063270 1090 Standard_Real& aChangeMinDist = aCounter >= 8 ? aModelMinDist : aGraphicMinDist;
1091 Standard_Real& aChangeMaxDist = aCounter >= 8 ? aModelMaxDist : aGraphicMaxDist;
6bc6a6fc 1092 aChangeMinDist = Min (aDistance, aChangeMinDist);
1093 aChangeMaxDist = Max (aDistance, aChangeMaxDist);
ed063270 1094 aCounter++;
6bc6a6fc 1095 }
1096
ea764884 1097 // Compute depth of bounding box center.
6bc6a6fc 1098 Standard_Real aMidDepth = (aGraphicMinDist + aGraphicMaxDist) * 0.5;
1099 Standard_Real aHalfDepth = (aGraphicMaxDist - aGraphicMinDist) * 0.5;
1100
ea764884 1101 // Compute enlarged or shrank near and far z ranges.
35c4a17c 1102 Standard_Real aZNear = aMidDepth - aHalfDepth * theScaleFactor;
1103 Standard_Real aZFar = aMidDepth + aHalfDepth * theScaleFactor;
6bc6a6fc 1104
1105 if (!IsOrthographic())
1106 {
ea764884 1107 // Everything is behind the perspective camera.
1108 if (aZFar < zEpsilon())
6bc6a6fc 1109 {
ea764884 1110 SetZRange (DEFAULT_ZNEAR, DEFAULT_ZFAR);
1111 return;
6bc6a6fc 1112 }
ea764884 1113
1114 // For better perspective the zNear value should not be less than zEpsilon (zFar).
1115 // If zNear computed by graphical boundaries do not meet the rule (e.g. it is negative
1116 // when computing it for grid) it could be increased up to minimum depth computed by
1117 // application min max values. This means that z-fit can sacrifice presentation of
1118 // non primary application graphical objects in favor of better perspective projection;
1119 if (aZNear < zEpsilon (aZFar))
6bc6a6fc 1120 {
ea764884 1121 // Otherwise it should be increased up to zEpsilon (1.0) to avoid clipping of primary
1122 // graphical objects.
1123 if (aModelMinDist < zEpsilon (aZFar))
1124 {
1125 aMidDepth = (aModelMinDist + aModelMaxDist) * 0.5;
1126 aHalfDepth = (aModelMinDist - aModelMaxDist) * 0.5;
1127 aZNear = Max (zEpsilon(), aMidDepth - aHalfDepth * theScaleFactor);
1128 }
1129 else
1130 {
1131 aZNear = zEpsilon (aZFar);
1132 }
6bc6a6fc 1133 }
1134 }
1135
ea764884 1136 //
1137 // Consider clipping errors due to double to single precision floating-point conversion.
1138 //
1139
1140 // Model to view transformation performs translation of points against eye position
1141 // in three dimensions. Both point coordinate and eye position values are converted from
1142 // double to single precision floating point numbers producing conversion errors.
1143 // Epsilon (Mod) * 3.0 should safely compensate precision error for z coordinate after
1144 // translation assuming that the:
1145 // Epsilon (Eye.Mod()) * 3.0 > Epsilon (Eye.X()) + Epsilon (Eye.Y()) + Epsilon (Eye.Z()).
1146 Standard_Real aEyeConf = 3.0 * zEpsilon (myEye.XYZ().Modulus());
1147
1148 // Model to view transformation performs rotation of points according to view direction.
1149 // New z coordinate is computed as a multiplication of point's x, y, z coordinates by the
1150 // "forward" direction vector's x, y, z coordinates. Both point's and "z" direction vector's
1151 // values are converted from double to single precision floating point numbers producing
1152 // conversion errors.
1153 // Epsilon (Mod) * 6.0 should safely compensate the precision errors for the multiplication
1154 // of point coordinates by direction vector.
1155 gp_Pnt aGraphicMin = theGraphicBB.CornerMin();
1156 gp_Pnt aGraphicMax = theGraphicBB.CornerMax();
1157
1158 Standard_Real aModelConf = 6.0 * zEpsilon (aGraphicMin.XYZ().Modulus()) +
1159 6.0 * zEpsilon (aGraphicMax.XYZ().Modulus());
1160
1161 // Compensate floating point conversion errors by increasing zNear, zFar to avoid clipping.
1162 aZNear -= zEpsilon (aZNear) + aEyeConf + aModelConf;
1163 aZFar += zEpsilon (aZFar) + aEyeConf + aModelConf;
1164
1165 if (!IsOrthographic())
6bc6a6fc 1166 {
ea764884 1167 // Compensate zNear, zFar conversion errors for perspective projection.
1168 aZNear -= aZFar * zEpsilon (aZNear) / (aZFar - zEpsilon (aZNear));
1169 aZFar += zEpsilon (aZFar);
1170
1171 // Ensure that after all the zNear is not a negative value.
1172 if (aZNear < zEpsilon())
1173 {
1174 aZNear = zEpsilon();
1175 }
6bc6a6fc 1176 }
1177
1178 SetZRange (aZNear, aZFar);
1179}