0029384: Visualization, TKOpenGl - basic integration with OpenVR
[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
b5ac8292 16#include <Graphic3d_Camera.hxx>
1beb58d7 17
18#include <gp_Pln.hxx>
19#include <gp_QuaternionNLerp.hxx>
20#include <gp_QuaternionSLerp.hxx>
825aa485 21#include <Graphic3d_Vec4.hxx>
22#include <Graphic3d_WorldViewProjState.hxx>
1beb58d7 23#include <NCollection_Sequence.hxx>
24#include <Standard_ShortReal.hxx>
b5ac8292 25#include <Standard_Atomic.hxx>
197ac94e 26#include <Standard_Assert.hxx>
b5ac8292 27
92efcf78 28IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_Camera,Standard_Transient)
29
b5ac8292 30namespace
31{
32 // (degrees -> radians) * 0.5
197ac94e 33 static const Standard_Real DTR_HALF = 0.5 * 0.0174532925;
34
35 // default property values
36 static const Standard_Real DEFAULT_ZNEAR = 0.001;
37 static const Standard_Real DEFAULT_ZFAR = 3000.0;
b5ac8292 38
39 // atomic state counter
40 static volatile Standard_Integer THE_STATE_COUNTER = 0;
3c648527 41
ea764884 42 // z-range tolerance compatible with for floating point.
43 static Standard_Real zEpsilon()
44 {
45 return FLT_EPSILON;
46 }
47
48 // relative z-range tolerance compatible with for floating point.
49 static Standard_Real zEpsilon (const Standard_Real theValue)
50 {
5c8908e0 51 Standard_Real anAbsValue = Abs (theValue);
52 if (anAbsValue <= (double)FLT_MIN)
825aa485 53 {
5c8908e0 54 return FLT_MIN;
825aa485 55 }
5c8908e0 56 Standard_Real aLogRadix = Log10 (anAbsValue) / Log10 (FLT_RADIX);
ea764884 57 Standard_Real aExp = Floor (aLogRadix);
58 return FLT_EPSILON * Pow (FLT_RADIX, aExp);
a3f6f591 59 }
1beb58d7 60
61 //! Convert camera definition to Ax3
62 gp_Ax3 cameraToAx3 (const Graphic3d_Camera& theCamera)
63 {
607e5e62 64 const gp_Dir aBackDir = -theCamera.Direction();
1beb58d7 65 const gp_Dir anXAxis (theCamera.Up().Crossed (aBackDir));
66 const gp_Dir anYAxis (aBackDir .Crossed (anXAxis));
67 const gp_Dir aZAxis (anXAxis .Crossed (anYAxis));
68 return gp_Ax3 (gp_Pnt (0.0, 0.0, 0.0), aZAxis, anXAxis);
69 }
a3f6f591 70}
b5ac8292 71
72// =======================================================================
73// function : Graphic3d_Camera
74// purpose :
75// =======================================================================
76Graphic3d_Camera::Graphic3d_Camera()
77: myUp (0.0, 1.0, 0.0),
607e5e62 78 myDirection (0.0, 0.0, 1.0),
b5ac8292 79 myEye (0.0, 0.0, -1500.0),
607e5e62 80 myDistance (1500.0),
b5ac8292 81 myAxialScale (1.0, 1.0, 1.0),
82 myProjType (Projection_Orthographic),
83 myFOVy (45.0),
b40cdc2b 84 myFOVx (45.0),
85 myFOV2d (180.0),
778cd667 86 myFOVyTan (Tan (DTR_HALF * 45.0)),
197ac94e 87 myZNear (DEFAULT_ZNEAR),
88 myZFar (DEFAULT_ZFAR),
b5ac8292 89 myAspect (1.0),
90 myScale (1000.0),
91 myZFocus (1.0),
92 myZFocusType (FocusType_Relative),
93 myIOD (0.05),
b40cdc2b 94 myIODType (IODType_Relative),
95 myIsCustomProjMatM (false),
96 myIsCustomProjMatLR(false),
97 myIsCustomFrustomLR(false)
b5ac8292 98{
825aa485 99 myWorldViewProjState.Initialize ((Standard_Size)Standard_Atomic_Increment (&THE_STATE_COUNTER),
100 (Standard_Size)Standard_Atomic_Increment (&THE_STATE_COUNTER),
101 this);
b5ac8292 102}
103
104// =======================================================================
105// function : Graphic3d_Camera
106// purpose :
107// =======================================================================
108Graphic3d_Camera::Graphic3d_Camera (const Handle(Graphic3d_Camera)& theOther)
c55c8fe9 109: myUp (0.0, 1.0, 0.0),
607e5e62 110 myDirection (0.0, 0.0, 1.0),
c55c8fe9 111 myEye (0.0, 0.0, -1500.0),
607e5e62 112 myDistance (1500.0),
c55c8fe9 113 myAxialScale (1.0, 1.0, 1.0),
114 myProjType (Projection_Orthographic),
115 myFOVy (45.0),
b40cdc2b 116 myFOVx (45.0),
117 myFOV2d (180.0),
c55c8fe9 118 myFOVyTan (Tan (DTR_HALF * 45.0)),
119 myZNear (DEFAULT_ZNEAR),
120 myZFar (DEFAULT_ZFAR),
121 myAspect (1.0),
122 myScale (1000.0),
123 myZFocus (1.0),
124 myZFocusType (FocusType_Relative),
125 myIOD (0.05),
b40cdc2b 126 myIODType (IODType_Relative),
127 myIsCustomProjMatM (false),
128 myIsCustomProjMatLR(false),
129 myIsCustomFrustomLR(false)
b5ac8292 130{
825aa485 131 myWorldViewProjState.Initialize (this);
132
b5ac8292 133 Copy (theOther);
134}
135
136// =======================================================================
137// function : CopyMappingData
138// purpose :
139// =======================================================================
140void Graphic3d_Camera::CopyMappingData (const Handle(Graphic3d_Camera)& theOtherCamera)
141{
bf02aa7d 142 SetFOVy (theOtherCamera->FOVy());
b40cdc2b 143 SetFOV2d (theOtherCamera->FOV2d());
bf02aa7d 144 SetZRange (theOtherCamera->ZNear(), theOtherCamera->ZFar());
145 SetAspect (theOtherCamera->Aspect());
146 SetScale (theOtherCamera->Scale());
147 SetZFocus (theOtherCamera->ZFocusType(), theOtherCamera->ZFocus());
148 SetIOD (theOtherCamera->GetIODType(), theOtherCamera->IOD());
149 SetProjectionType (theOtherCamera->ProjectionType());
3bffef55 150 SetTile (theOtherCamera->myTile);
b40cdc2b 151
152 ResetCustomProjection();
153 if (theOtherCamera->IsCustomStereoProjection())
154 {
155 SetCustomStereoProjection (theOtherCamera->myCustomProjMatL, theOtherCamera->myCustomProjMatR);
156 }
157 else if (theOtherCamera->IsCustomStereoFrustum())
158 {
159 SetCustomStereoFrustums (theOtherCamera->myCustomFrustumL, theOtherCamera->myCustomFrustumR);
160 }
161 if (theOtherCamera->IsCustomMonoProjection())
162 {
163 SetCustomMonoProjection (theOtherCamera->myCustomProjMatM);
164 }
b5ac8292 165}
166
167// =======================================================================
168// function : CopyOrientationData
169// purpose :
170// =======================================================================
171void Graphic3d_Camera::CopyOrientationData (const Handle(Graphic3d_Camera)& theOtherCamera)
172{
607e5e62 173 if (!myEye.IsEqual (theOtherCamera->Eye(), 0.0)
174 || !myUp.IsEqual (theOtherCamera->Up(), 0.0)
175 || !myDirection.IsEqual (theOtherCamera->Direction(), 0.0)
176 || myDistance != theOtherCamera->Distance())
177 {
178 myEye = theOtherCamera->Eye();
179 myUp = theOtherCamera->Up();
180 myDirection = theOtherCamera->Direction();
181 myDistance = theOtherCamera->Distance();
182 InvalidateOrientation();
183 }
bf02aa7d 184 SetAxialScale (theOtherCamera->AxialScale());
b5ac8292 185}
186
187// =======================================================================
188// function : Copy
189// purpose :
190// =======================================================================
191void Graphic3d_Camera::Copy (const Handle(Graphic3d_Camera)& theOther)
192{
b5ac8292 193 CopyMappingData (theOther);
194 CopyOrientationData (theOther);
b5ac8292 195}
196
607e5e62 197// =======================================================================
198// function : MoveEyeTo
199// purpose :
200// =======================================================================
201void Graphic3d_Camera::MoveEyeTo (const gp_Pnt& theEye)
202{
203 if (myEye.IsEqual (theEye, 0.0))
204 {
205 return;
206 }
207
208 myEye = theEye;
209 InvalidateOrientation();
210}
211
212// =======================================================================
213// function : SetEyeAndCenter
214// purpose :
215// =======================================================================
216void Graphic3d_Camera::SetEyeAndCenter (const gp_Pnt& theEye,
217 const gp_Pnt& theCenter)
218{
219 if (Eye() .IsEqual (theEye, 0.0)
220 && Center().IsEqual (theCenter, 0.0))
221 {
222 return;
223 }
224
225 myEye = theEye;
226 myDistance = theEye.Distance (theCenter);
227 if (myDistance > gp::Resolution())
228 {
229 myDirection = gp_Dir (theCenter.XYZ() - theEye.XYZ());
230 }
231 InvalidateOrientation();
232}
233
b5ac8292 234// =======================================================================
235// function : SetEye
236// purpose :
237// =======================================================================
238void Graphic3d_Camera::SetEye (const gp_Pnt& theEye)
239{
bf02aa7d 240 if (Eye().IsEqual (theEye, 0.0))
241 {
242 return;
243 }
244
607e5e62 245 const gp_Pnt aCenter = Center();
b5ac8292 246 myEye = theEye;
607e5e62 247 myDistance = myEye.Distance (aCenter);
248 if (myDistance > gp::Resolution())
249 {
250 myDirection = gp_Dir (aCenter.XYZ() - myEye.XYZ());
251 }
197ac94e 252 InvalidateOrientation();
b5ac8292 253}
254
255// =======================================================================
256// function : SetCenter
257// purpose :
258// =======================================================================
259void Graphic3d_Camera::SetCenter (const gp_Pnt& theCenter)
260{
607e5e62 261 const Standard_Real aDistance = myEye.Distance (theCenter);
262 if (myDistance == aDistance)
bf02aa7d 263 {
264 return;
265 }
266
607e5e62 267 myDistance = aDistance;
268 if (myDistance > gp::Resolution())
269 {
270 myDirection = gp_Dir (theCenter.XYZ() - myEye.XYZ());
271 }
197ac94e 272 InvalidateOrientation();
b5ac8292 273}
274
275// =======================================================================
276// function : SetUp
277// purpose :
278// =======================================================================
279void Graphic3d_Camera::SetUp (const gp_Dir& theUp)
280{
bf02aa7d 281 if (Up().IsEqual (theUp, 0.0))
282 {
283 return;
284 }
285
b5ac8292 286 myUp = theUp;
197ac94e 287 InvalidateOrientation();
b5ac8292 288}
289
290// =======================================================================
291// function : SetAxialScale
292// purpose :
293// =======================================================================
197ac94e 294void Graphic3d_Camera::SetAxialScale (const gp_XYZ& theAxialScale)
b5ac8292 295{
bf02aa7d 296 if (AxialScale().IsEqual (theAxialScale, 0.0))
297 {
298 return;
299 }
300
b5ac8292 301 myAxialScale = theAxialScale;
197ac94e 302 InvalidateOrientation();
b5ac8292 303}
304
305// =======================================================================
306// function : SetDistance
307// purpose :
308// =======================================================================
309void Graphic3d_Camera::SetDistance (const Standard_Real theDistance)
310{
607e5e62 311 if (myDistance == theDistance)
bf02aa7d 312 {
313 return;
314 }
315
607e5e62 316 const gp_Pnt aCenter = Center();
317 myDistance = theDistance;
318 myEye = aCenter.XYZ() - myDirection.XYZ() * myDistance;
319 InvalidateOrientation();
b5ac8292 320}
321
322// =======================================================================
607e5e62 323// function : SetDirectionFromEye
b5ac8292 324// purpose :
325// =======================================================================
607e5e62 326void Graphic3d_Camera::SetDirectionFromEye (const gp_Dir& theDir)
b5ac8292 327{
607e5e62 328 if (myDirection.IsEqual (theDir, 0.0))
329 {
330 return;
331 }
332
333 myDirection = theDir;
334 InvalidateOrientation();
b5ac8292 335}
336
337// =======================================================================
338// function : SetDirection
339// purpose :
340// =======================================================================
341void Graphic3d_Camera::SetDirection (const gp_Dir& theDir)
342{
607e5e62 343 if (myDirection.IsEqual (theDir, 0.0))
bf02aa7d 344 {
345 return;
346 }
347
607e5e62 348 const gp_Pnt aCenter = Center();
349 myDirection = theDir;
350 myEye = aCenter.XYZ() - theDir.XYZ() * myDistance;
351 InvalidateOrientation();
b5ac8292 352}
353
354// =======================================================================
355// function : SetScale
356// purpose :
357// =======================================================================
358void Graphic3d_Camera::SetScale (const Standard_Real theScale)
359{
c357e426 360 if (Scale() == theScale)
361 {
362 return;
363 }
364
b5ac8292 365 myScale = theScale;
366
367 switch (myProjType)
368 {
369 case Projection_Perspective :
370 case Projection_Stereo :
371 case Projection_MonoLeftEye :
372 case Projection_MonoRightEye :
373 {
778cd667 374 Standard_Real aDistance = theScale * 0.5 / myFOVyTan;
b5ac8292 375 SetDistance (aDistance);
376 }
377
378 default :
379 break;
380 }
381
197ac94e 382 InvalidateProjection();
b5ac8292 383}
384
385// =======================================================================
386// function : Scale
387// purpose :
388// =======================================================================
389Standard_Real Graphic3d_Camera::Scale() const
390{
391 switch (myProjType)
392 {
393 case Projection_Orthographic :
394 return myScale;
395
396 // case Projection_Perspective :
397 // case Projection_Stereo :
398 // case Projection_MonoLeftEye :
399 // case Projection_MonoRightEye :
400 default :
778cd667 401 return Distance() * 2.0 * myFOVyTan;
b5ac8292 402 }
403}
404
405// =======================================================================
406// function : SetProjectionType
407// purpose :
408// =======================================================================
409void Graphic3d_Camera::SetProjectionType (const Projection theProjectionType)
410{
c357e426 411 Projection anOldType = ProjectionType();
b5ac8292 412
413 if (anOldType == theProjectionType)
414 {
415 return;
416 }
417
197ac94e 418 if (anOldType == Projection_Orthographic)
b5ac8292 419 {
197ac94e 420 if (myZNear <= RealEpsilon())
421 {
422 myZNear = DEFAULT_ZNEAR;
423 }
424 if (myZFar <= RealEpsilon())
425 {
426 myZFar = DEFAULT_ZFAR;
427 }
b5ac8292 428 }
429
197ac94e 430 myProjType = theProjectionType;
431
432 InvalidateProjection();
b5ac8292 433}
434
435// =======================================================================
436// function : SetFOVy
437// purpose :
438// =======================================================================
439void Graphic3d_Camera::SetFOVy (const Standard_Real theFOVy)
440{
c357e426 441 if (FOVy() == theFOVy)
442 {
443 return;
444 }
445
b5ac8292 446 myFOVy = theFOVy;
b40cdc2b 447 myFOVx = theFOVy * myAspect;
778cd667 448 myFOVyTan = Tan(DTR_HALF * myFOVy);
c357e426 449
197ac94e 450 InvalidateProjection();
b5ac8292 451}
452
b40cdc2b 453// =======================================================================
454// function : SetFOV2d
455// purpose :
456// =======================================================================
457void Graphic3d_Camera::SetFOV2d (const Standard_Real theFOV)
458{
459 if (FOV2d() == theFOV)
460 {
461 return;
462 }
463
464 myFOV2d = theFOV;
465 InvalidateProjection();
466}
467
b5ac8292 468// =======================================================================
197ac94e 469// function : SetZRange
b5ac8292 470// purpose :
471// =======================================================================
197ac94e 472void Graphic3d_Camera::SetZRange (const Standard_Real theZNear,
473 const Standard_Real theZFar)
b5ac8292 474{
197ac94e 475 Standard_ASSERT_RAISE (theZFar > theZNear, "ZFar should be greater than ZNear");
476 if (!IsOrthographic())
b5ac8292 477 {
197ac94e 478 Standard_ASSERT_RAISE (theZNear > 0.0, "Only positive Z-Near is allowed for perspective camera");
479 Standard_ASSERT_RAISE (theZFar > 0.0, "Only positive Z-Far is allowed for perspective camera");
b5ac8292 480 }
481
c357e426 482 if (ZNear() == theZNear
483 && ZFar () == theZFar)
484 {
485 return;
486 }
487
197ac94e 488 myZNear = theZNear;
489 myZFar = theZFar;
b5ac8292 490
197ac94e 491 InvalidateProjection();
b5ac8292 492}
493
494// =======================================================================
495// function : SetAspect
496// purpose :
497// =======================================================================
498void Graphic3d_Camera::SetAspect (const Standard_Real theAspect)
499{
c357e426 500 if (Aspect() == theAspect)
501 {
502 return;
503 }
504
b5ac8292 505 myAspect = theAspect;
b40cdc2b 506 myFOVx = myFOVy * theAspect;
c357e426 507
197ac94e 508 InvalidateProjection();
b5ac8292 509}
510
511// =======================================================================
512// function : SetZFocus
513// purpose :
514// =======================================================================
515void Graphic3d_Camera::SetZFocus(const FocusType theType, const Standard_Real theZFocus)
516{
c357e426 517 if (ZFocusType() == theType
518 && ZFocus () == theZFocus)
519 {
520 return;
521 }
522
b5ac8292 523 myZFocusType = theType;
c357e426 524 myZFocus = theZFocus;
525
197ac94e 526 InvalidateProjection();
b5ac8292 527}
528
529// =======================================================================
530// function : SetIOD
531// purpose :
532// =======================================================================
533void Graphic3d_Camera::SetIOD (const IODType theType, const Standard_Real theIOD)
534{
bf02aa7d 535 if (GetIODType() == theType
536 && IOD () == theIOD)
c357e426 537 {
538 return;
539 }
540
b5ac8292 541 myIODType = theType;
c357e426 542 myIOD = theIOD;
543
197ac94e 544 InvalidateProjection();
b5ac8292 545}
546
3bffef55 547// =======================================================================
548// function : SetTile
549// purpose :
550// =======================================================================
551void Graphic3d_Camera::SetTile (const Graphic3d_CameraTile& theTile)
552{
553 if (myTile == theTile)
554 {
555 return;
556 }
557
558 myTile = theTile;
559 InvalidateProjection();
560}
561
b5ac8292 562// =======================================================================
563// function : OrthogonalizeUp
564// purpose :
565// =======================================================================
566void Graphic3d_Camera::OrthogonalizeUp()
567{
197ac94e 568 SetUp (OrthogonalizedUp());
b5ac8292 569}
570
571// =======================================================================
197ac94e 572// function : OrthogonalizedUp
b5ac8292 573// purpose :
574// =======================================================================
197ac94e 575gp_Dir Graphic3d_Camera::OrthogonalizedUp() const
b5ac8292 576{
197ac94e 577 gp_Dir aDir = Direction();
578 gp_Dir aLeft = aDir.Crossed (Up());
b5ac8292 579
197ac94e 580 // recompute up as: up = left x direction
581 return aLeft.Crossed (aDir);
b5ac8292 582}
583
584// =======================================================================
585// function : Transform
586// purpose :
587// =======================================================================
588void Graphic3d_Camera::Transform (const gp_Trsf& theTrsf)
589{
bf02aa7d 590 if (theTrsf.Form() == gp_Identity)
591 {
592 return;
593 }
594
607e5e62 595 myUp .Transform (theTrsf);
596 myDirection.Transform (theTrsf);
597 myEye.Transform (theTrsf);
598 InvalidateOrientation();
b5ac8292 599}
600
601// =======================================================================
602// function : safePointCast
603// purpose :
604// =======================================================================
197ac94e 605static Graphic3d_Vec4d safePointCast (const gp_Pnt& thePnt)
b5ac8292 606{
607 Standard_Real aLim = 1e15f;
197ac94e 608
b5ac8292 609 // have to deal with values greater then max float
610 gp_Pnt aSafePoint = thePnt;
611 const Standard_Real aBigFloat = aLim * 0.1f;
612 if (Abs (aSafePoint.X()) > aLim)
613 aSafePoint.SetX (aSafePoint.X() >= 0 ? aBigFloat : -aBigFloat);
614 if (Abs (aSafePoint.Y()) > aLim)
615 aSafePoint.SetY (aSafePoint.Y() >= 0 ? aBigFloat : -aBigFloat);
616 if (Abs (aSafePoint.Z()) > aLim)
617 aSafePoint.SetZ (aSafePoint.Z() >= 0 ? aBigFloat : -aBigFloat);
618
619 // convert point
197ac94e 620 Graphic3d_Vec4d aPnt (aSafePoint.X(), aSafePoint.Y(), aSafePoint.Z(), 1.0);
b5ac8292 621
622 return aPnt;
623}
624
625// =======================================================================
626// function : Project
627// purpose :
628// =======================================================================
629gp_Pnt Graphic3d_Camera::Project (const gp_Pnt& thePnt) const
630{
197ac94e 631 const Graphic3d_Mat4d& aViewMx = OrientationMatrix();
632 const Graphic3d_Mat4d& aProjMx = ProjectionMatrix();
b5ac8292 633
634 // use compatible type of point
197ac94e 635 Graphic3d_Vec4d aPnt = safePointCast (thePnt);
b5ac8292 636
637 aPnt = aViewMx * aPnt; // convert to view coordinate space
638 aPnt = aProjMx * aPnt; // convert to projection coordinate space
639
640 const Standard_Real aInvW = 1.0 / Standard_Real (aPnt.w());
641
642 return gp_Pnt (aPnt.x() * aInvW, aPnt.y() * aInvW, aPnt.z() * aInvW);
643}
644
645// =======================================================================
646// function : UnProject
647// purpose :
648// =======================================================================
649gp_Pnt Graphic3d_Camera::UnProject (const gp_Pnt& thePnt) const
650{
197ac94e 651 const Graphic3d_Mat4d& aViewMx = OrientationMatrix();
652 const Graphic3d_Mat4d& aProjMx = ProjectionMatrix();
b5ac8292 653
197ac94e 654 Graphic3d_Mat4d aInvView;
655 Graphic3d_Mat4d aInvProj;
b5ac8292 656
657 // this case should never happen
658 if (!aViewMx.Inverted (aInvView) || !aProjMx.Inverted (aInvProj))
659 {
660 return gp_Pnt (0.0, 0.0, 0.0);
661 }
662
663 // use compatible type of point
197ac94e 664 Graphic3d_Vec4d aPnt = safePointCast (thePnt);
b5ac8292 665
666 aPnt = aInvProj * aPnt; // convert to view coordinate space
667 aPnt = aInvView * aPnt; // convert to world coordinate space
668
669 const Standard_Real aInvW = 1.0 / Standard_Real (aPnt.w());
670
671 return gp_Pnt (aPnt.x() * aInvW, aPnt.y() * aInvW, aPnt.z() * aInvW);
672}
673
674// =======================================================================
675// function : ConvertView2Proj
676// purpose :
677// =======================================================================
678gp_Pnt Graphic3d_Camera::ConvertView2Proj (const gp_Pnt& thePnt) const
679{
197ac94e 680 const Graphic3d_Mat4d& aProjMx = ProjectionMatrix();
b5ac8292 681
682 // use compatible type of point
197ac94e 683 Graphic3d_Vec4d aPnt = safePointCast (thePnt);
b5ac8292 684
685 aPnt = aProjMx * aPnt; // convert to projection coordinate space
686
687 const Standard_Real aInvW = 1.0 / Standard_Real (aPnt.w());
688
689 return gp_Pnt (aPnt.x() * aInvW, aPnt.y() * aInvW, aPnt.z() * aInvW);
690}
691
692// =======================================================================
693// function : ConvertProj2View
694// purpose :
695// =======================================================================
696gp_Pnt Graphic3d_Camera::ConvertProj2View (const gp_Pnt& thePnt) const
697{
197ac94e 698 const Graphic3d_Mat4d& aProjMx = ProjectionMatrix();
b5ac8292 699
197ac94e 700 Graphic3d_Mat4d aInvProj;
b5ac8292 701
702 // this case should never happen, but...
703 if (!aProjMx.Inverted (aInvProj))
704 {
197ac94e 705 return gp_Pnt (0, 0, 0);
b5ac8292 706 }
707
708 // use compatible type of point
197ac94e 709 Graphic3d_Vec4d aPnt = safePointCast (thePnt);
b5ac8292 710
711 aPnt = aInvProj * aPnt; // convert to view coordinate space
712
713 const Standard_Real aInvW = 1.0 / Standard_Real (aPnt.w());
714
715 return gp_Pnt (aPnt.x() * aInvW, aPnt.y() * aInvW, aPnt.z() * aInvW);
716}
717
718// =======================================================================
719// function : ConvertWorld2View
720// purpose :
721// =======================================================================
722gp_Pnt Graphic3d_Camera::ConvertWorld2View (const gp_Pnt& thePnt) const
723{
197ac94e 724 const Graphic3d_Mat4d& aViewMx = OrientationMatrix();
b5ac8292 725
726 // use compatible type of point
197ac94e 727 Graphic3d_Vec4d aPnt = safePointCast (thePnt);
b5ac8292 728
729 aPnt = aViewMx * aPnt; // convert to view coordinate space
730
731 const Standard_Real aInvW = 1.0 / Standard_Real (aPnt.w());
732
733 return gp_Pnt (aPnt.x() * aInvW, aPnt.y() * aInvW, aPnt.z() * aInvW);
734}
735
736// =======================================================================
737// function : ConvertView2World
738// purpose :
739// =======================================================================
740gp_Pnt Graphic3d_Camera::ConvertView2World (const gp_Pnt& thePnt) const
741{
197ac94e 742 const Graphic3d_Mat4d& aViewMx = OrientationMatrix();
b5ac8292 743
197ac94e 744 Graphic3d_Mat4d aInvView;
b5ac8292 745
746 if (!aViewMx.Inverted (aInvView))
747 {
748 return gp_Pnt(0, 0, 0);
749 }
750
751 // use compatible type of point
197ac94e 752 Graphic3d_Vec4d aPnt = safePointCast (thePnt);
b5ac8292 753
754 aPnt = aInvView * aPnt; // convert to world coordinate space
755
756 const Standard_Real aInvW = 1.0 / Standard_Real (aPnt.w());
757
758 return gp_Pnt (aPnt.x() * aInvW, aPnt.y() * aInvW, aPnt.z() * aInvW);
759}
760
761// =======================================================================
762// function : ViewDimensions
763// purpose :
764// =======================================================================
3fe9ce0e 765gp_XYZ Graphic3d_Camera::ViewDimensions (const Standard_Real theZValue) const
b5ac8292 766{
767 // view plane dimensions
778cd667 768 Standard_Real aSize = IsOrthographic() ? myScale : (2.0 * theZValue * myFOVyTan);
539d3a1b 769 Standard_Real aSizeX, aSizeY;
770 if (myAspect > 1.0)
771 {
772 aSizeX = aSize * myAspect;
773 aSizeY = aSize;
774 }
775 else
776 {
777 aSizeX = aSize;
778 aSizeY = aSize / myAspect;
779 }
b5ac8292 780
781 // and frustum depth
197ac94e 782 return gp_XYZ (aSizeX, aSizeY, myZFar - myZNear);
b5ac8292 783}
784
785// =======================================================================
197ac94e 786// function : Frustum
b5ac8292 787// purpose :
788// =======================================================================
197ac94e 789void Graphic3d_Camera::Frustum (gp_Pln& theLeft,
790 gp_Pln& theRight,
791 gp_Pln& theBottom,
792 gp_Pln& theTop,
793 gp_Pln& theNear,
794 gp_Pln& theFar) const
b5ac8292 795{
197ac94e 796 gp_Vec aProjection = gp_Vec (Direction());
797 gp_Vec anUp = OrthogonalizedUp();
798 gp_Vec aSide = aProjection ^ anUp;
799
800 Standard_ASSERT_RAISE (
801 !aProjection.IsParallel (anUp, Precision::Angular()),
802 "Can not derive SIDE = PROJ x UP - directions are parallel");
803
804 theNear = gp_Pln (Eye().Translated (aProjection * ZNear()), aProjection);
805 theFar = gp_Pln (Eye().Translated (aProjection * ZFar()), -aProjection);
806
a4d594cb 807 Standard_Real aHScaleHor = 0.0, aHScaleVer = 0.0;
808 if (Aspect() >= 1.0)
809 {
810 aHScaleHor = Scale() * 0.5 * Aspect();
811 aHScaleVer = Scale() * 0.5;
812 }
813 else
814 {
815 aHScaleHor = Scale() * 0.5;
816 aHScaleVer = Scale() * 0.5 / Aspect();
817 }
197ac94e 818
819 gp_Pnt aPntLeft = Center().Translated (aHScaleHor * -aSide);
820 gp_Pnt aPntRight = Center().Translated (aHScaleHor * aSide);
821 gp_Pnt aPntBottom = Center().Translated (aHScaleVer * -anUp);
822 gp_Pnt aPntTop = Center().Translated (aHScaleVer * anUp);
823
824 gp_Vec aDirLeft = aSide;
825 gp_Vec aDirRight = -aSide;
826 gp_Vec aDirBottom = anUp;
827 gp_Vec aDirTop = -anUp;
828 if (!IsOrthographic())
829 {
830 Standard_Real aHFOVHor = ATan (Tan (DTR_HALF * FOVy()) * Aspect());
831 Standard_Real aHFOVVer = DTR_HALF * FOVy();
832 aDirLeft.Rotate (gp_Ax1 (gp::Origin(), anUp), aHFOVHor);
833 aDirRight.Rotate (gp_Ax1 (gp::Origin(), anUp), -aHFOVHor);
834 aDirBottom.Rotate (gp_Ax1 (gp::Origin(), aSide), -aHFOVVer);
835 aDirTop.Rotate (gp_Ax1 (gp::Origin(), aSide), aHFOVVer);
836 }
837
838 theLeft = gp_Pln (aPntLeft, aDirLeft);
839 theRight = gp_Pln (aPntRight, aDirRight);
840 theBottom = gp_Pln (aPntBottom, aDirBottom);
841 theTop = gp_Pln (aPntTop, aDirTop);
842}
843
844// =======================================================================
845// function : OrientationMatrix
846// purpose :
847// =======================================================================
848const Graphic3d_Mat4d& Graphic3d_Camera::OrientationMatrix() const
849{
778cd667 850 return UpdateOrientation (myMatricesD).Orientation;
197ac94e 851}
852
853// =======================================================================
854// function : OrientationMatrixF
855// purpose :
856// =======================================================================
857const Graphic3d_Mat4& Graphic3d_Camera::OrientationMatrixF() const
858{
778cd667 859 return UpdateOrientation (myMatricesF).Orientation;
197ac94e 860}
861
862// =======================================================================
863// function : ProjectionMatrix
864// purpose :
865// =======================================================================
866const Graphic3d_Mat4d& Graphic3d_Camera::ProjectionMatrix() const
867{
778cd667 868 return UpdateProjection (myMatricesD).MProjection;
197ac94e 869}
870
871// =======================================================================
872// function : ProjectionMatrixF
873// purpose :
874// =======================================================================
875const Graphic3d_Mat4& Graphic3d_Camera::ProjectionMatrixF() const
876{
778cd667 877 return UpdateProjection (myMatricesF).MProjection;
197ac94e 878}
879
880// =======================================================================
881// function : ProjectionStereoLeft
882// purpose :
883// =======================================================================
884const Graphic3d_Mat4d& Graphic3d_Camera::ProjectionStereoLeft() const
885{
778cd667 886 return UpdateProjection (myMatricesD).LProjection;
197ac94e 887}
888
889// =======================================================================
890// function : ProjectionStereoLeftF
891// purpose :
892// =======================================================================
893const Graphic3d_Mat4& Graphic3d_Camera::ProjectionStereoLeftF() const
894{
778cd667 895 return UpdateProjection (myMatricesF).LProjection;
197ac94e 896}
897
898// =======================================================================
899// function : ProjectionStereoRight
900// purpose :
901// =======================================================================
902const Graphic3d_Mat4d& Graphic3d_Camera::ProjectionStereoRight() const
903{
778cd667 904 return UpdateProjection (myMatricesD).RProjection;
197ac94e 905}
906
907// =======================================================================
908// function : ProjectionStereoRightF
909// purpose :
910// =======================================================================
911const Graphic3d_Mat4& Graphic3d_Camera::ProjectionStereoRightF() const
912{
778cd667 913 return UpdateProjection (myMatricesF).RProjection;
b5ac8292 914}
915
b40cdc2b 916// =======================================================================
917// function : ResetCustomProjection
918// purpose :
919// =======================================================================
920void Graphic3d_Camera::ResetCustomProjection()
921{
922 if (myIsCustomFrustomLR
923 || myIsCustomProjMatLR
924 || myIsCustomProjMatM)
925 {
926 myIsCustomFrustomLR = false;
927 myIsCustomProjMatLR = false;
928 myIsCustomProjMatM = false;
929 InvalidateProjection();
930 }
931}
932
933// =======================================================================
934// function : SetCustomStereoFrustums
935// purpose :
936// =======================================================================
937void Graphic3d_Camera::SetCustomStereoFrustums (const Aspect_FrustumLRBT<Standard_Real>& theFrustumL,
938 const Aspect_FrustumLRBT<Standard_Real>& theFrustumR)
939{
940 myCustomFrustumL = theFrustumL;
941 myCustomFrustumR = theFrustumR;
942 myIsCustomFrustomLR = true;
943 myIsCustomProjMatLR = false;
944 InvalidateProjection();
945}
946
947// =======================================================================
948// function : SetCustomStereoProjection
949// purpose :
950// =======================================================================
951void Graphic3d_Camera::SetCustomStereoProjection (const Graphic3d_Mat4d& theProjL,
952 const Graphic3d_Mat4d& theProjR)
953{
954 myCustomProjMatL = theProjL;
955 myCustomProjMatR = theProjR;
956 myIsCustomProjMatLR = true;
957 myIsCustomFrustomLR = false;
958 InvalidateProjection();
959}
960
961// =======================================================================
962// function : SetCustomMonoProjection
963// purpose :
964// =======================================================================
965void Graphic3d_Camera::SetCustomMonoProjection (const Graphic3d_Mat4d& theProj)
966{
967 myCustomProjMatM = theProj;
968 myIsCustomProjMatM = true;
969 InvalidateProjection();
970}
971
b5ac8292 972// =======================================================================
973// function : UpdateProjection
974// purpose :
975// =======================================================================
197ac94e 976template <typename Elem_t>
977Graphic3d_Camera::TransformMatrices<Elem_t>&
978 Graphic3d_Camera::UpdateProjection (TransformMatrices<Elem_t>& theMatrices) const
b5ac8292 979{
197ac94e 980 if (theMatrices.IsProjectionValid())
b5ac8292 981 {
197ac94e 982 return theMatrices; // for inline accessors
b5ac8292 983 }
984
197ac94e 985 theMatrices.InitProjection();
b5ac8292 986
987 // sets top of frustum based on FOVy and near clipping plane
197ac94e 988 Elem_t aScale = static_cast<Elem_t> (myScale);
989 Elem_t aZNear = static_cast<Elem_t> (myZNear);
990 Elem_t aZFar = static_cast<Elem_t> (myZFar);
991 Elem_t anAspect = static_cast<Elem_t> (myAspect);
ab1c121b 992 Elem_t aDXHalf = 0.0, aDYHalf = 0.0;
b5ac8292 993 if (IsOrthographic())
994 {
b40cdc2b 995 aDXHalf = aDYHalf = aScale * Elem_t (0.5);
b5ac8292 996 }
997 else
998 {
b40cdc2b 999 aDXHalf = aDYHalf = aZNear * Elem_t (myFOVyTan);
b5ac8292 1000 }
1001
ab1c121b 1002 if (anAspect > 1.0)
1003 {
1004 aDXHalf *= anAspect;
1005 }
1006 else
1007 {
1008 aDYHalf /= anAspect;
1009 }
1010
b5ac8292 1011 // sets right of frustum based on aspect ratio
b40cdc2b 1012 Aspect_FrustumLRBT<Elem_t> anLRBT;
1013 anLRBT.Left = -aDXHalf;
1014 anLRBT.Right = aDXHalf;
1015 anLRBT.Bottom = -aDYHalf;
1016 anLRBT.Top = aDYHalf;
b5ac8292 1017
197ac94e 1018 Elem_t aIOD = myIODType == IODType_Relative
1019 ? static_cast<Elem_t> (myIOD * Distance())
1020 : static_cast<Elem_t> (myIOD);
b5ac8292 1021
197ac94e 1022 Elem_t aFocus = myZFocusType == FocusType_Relative
1023 ? static_cast<Elem_t> (myZFocus * Distance())
1024 : static_cast<Elem_t> (myZFocus);
b5ac8292 1025
3bffef55 1026 if (myTile.IsValid())
1027 {
1028 const Elem_t aDXFull = Elem_t(2) * aDXHalf;
1029 const Elem_t aDYFull = Elem_t(2) * aDYHalf;
1030 const Graphic3d_Vec2i anOffset = myTile.OffsetLowerLeft();
b40cdc2b 1031 anLRBT.Left = -aDXHalf + aDXFull * static_cast<Elem_t> (anOffset.x()) / static_cast<Elem_t> (myTile.TotalSize.x());
1032 anLRBT.Right = -aDXHalf + aDXFull * static_cast<Elem_t> (anOffset.x() + myTile.TileSize.x()) / static_cast<Elem_t> (myTile.TotalSize.x());
1033 anLRBT.Bottom = -aDYHalf + aDYFull * static_cast<Elem_t> (anOffset.y()) / static_cast<Elem_t> (myTile.TotalSize.y());
1034 anLRBT.Top = -aDYHalf + aDYFull * static_cast<Elem_t> (anOffset.y() + myTile.TileSize.y()) / static_cast<Elem_t> (myTile.TotalSize.y());
3bffef55 1035 }
1036
b40cdc2b 1037 if (myIsCustomProjMatM)
1038 {
1039 theMatrices.MProjection.ConvertFrom (myCustomProjMatM);
1040 }
b5ac8292 1041 switch (myProjType)
1042 {
b40cdc2b 1043 case Projection_Orthographic:
b5ac8292 1044 {
b40cdc2b 1045 if (!myIsCustomProjMatM)
1046 {
1047 orthoProj (theMatrices.MProjection, anLRBT, aZNear, aZFar);
1048 }
b5ac8292 1049 break;
1050 }
b40cdc2b 1051 case Projection_Perspective:
b5ac8292 1052 {
b40cdc2b 1053 if (!myIsCustomProjMatM)
1054 {
1055 perspectiveProj (theMatrices.MProjection, anLRBT, aZNear, aZFar);
1056 }
b5ac8292 1057 break;
1058 }
b40cdc2b 1059 case Projection_MonoLeftEye:
1060 case Projection_MonoRightEye:
1061 case Projection_Stereo:
b5ac8292 1062 {
b40cdc2b 1063 if (!myIsCustomProjMatM)
1064 {
1065 perspectiveProj (theMatrices.MProjection, anLRBT, aZNear, aZFar);
1066 }
1067 if (myIsCustomProjMatLR)
1068 {
1069 theMatrices.LProjection.ConvertFrom (myCustomProjMatL);
1070 theMatrices.RProjection.ConvertFrom (myCustomProjMatR);
1071 }
1072 else if (myIsCustomFrustomLR)
1073 {
1074 anLRBT = Aspect_FrustumLRBT<Elem_t> (myCustomFrustumL).Multiplied (aZNear);
1075 perspectiveProj (theMatrices.LProjection, anLRBT, aZNear, aZFar);
1076 if (aIOD != Elem_t (0.0))
1077 {
1078 theMatrices.LProjection.Translate (NCollection_Vec3<Elem_t> (Elem_t (0.5) * aIOD, Elem_t (0.0), Elem_t (0.0)));
1079 }
1080
1081 anLRBT = Aspect_FrustumLRBT<Elem_t> (myCustomFrustumR).Multiplied (aZNear);
1082 perspectiveProj (theMatrices.RProjection, anLRBT, aZNear, aZFar);
1083 if (aIOD != Elem_t (0.0))
1084 {
1085 theMatrices.RProjection.Translate (NCollection_Vec3<Elem_t> (Elem_t (-0.5) * aIOD, Elem_t (0.0), Elem_t (0.0)));
1086 }
1087 }
1088 else
1089 {
1090 stereoEyeProj (theMatrices.LProjection,
1091 anLRBT, aZNear, aZFar, aIOD, aFocus,
1092 Aspect_Eye_Left);
1093 stereoEyeProj (theMatrices.RProjection,
1094 anLRBT, aZNear, aZFar, aIOD, aFocus,
1095 Aspect_Eye_Right);
1096 }
b5ac8292 1097 break;
1098 }
1099 }
b40cdc2b 1100 if (myProjType == Projection_MonoLeftEye)
1101 {
1102 theMatrices.MProjection = theMatrices.LProjection;
1103 }
1104 else if (myProjType == Projection_MonoRightEye)
1105 {
1106 theMatrices.MProjection = theMatrices.RProjection;
1107 }
197ac94e 1108
1109 return theMatrices; // for inline accessors
b5ac8292 1110}
1111
1112// =======================================================================
1113// function : UpdateOrientation
1114// purpose :
1115// =======================================================================
197ac94e 1116template <typename Elem_t>
1117Graphic3d_Camera::TransformMatrices<Elem_t>&
1118 Graphic3d_Camera::UpdateOrientation (TransformMatrices<Elem_t>& theMatrices) const
b5ac8292 1119{
197ac94e 1120 if (theMatrices.IsOrientationValid())
b5ac8292 1121 {
197ac94e 1122 return theMatrices; // for inline accessors
b5ac8292 1123 }
1124
197ac94e 1125 theMatrices.InitOrientation();
1126
1127 NCollection_Vec3<Elem_t> anEye (static_cast<Elem_t> (myEye.X()),
1128 static_cast<Elem_t> (myEye.Y()),
1129 static_cast<Elem_t> (myEye.Z()));
1130
607e5e62 1131 NCollection_Vec3<Elem_t> aViewDir (static_cast<Elem_t> (myDirection.X()),
1132 static_cast<Elem_t> (myDirection.Y()),
1133 static_cast<Elem_t> (myDirection.Z()));
b5ac8292 1134
197ac94e 1135 NCollection_Vec3<Elem_t> anUp (static_cast<Elem_t> (myUp.X()),
1136 static_cast<Elem_t> (myUp.Y()),
1137 static_cast<Elem_t> (myUp.Z()));
b5ac8292 1138
197ac94e 1139 NCollection_Vec3<Elem_t> anAxialScale (static_cast<Elem_t> (myAxialScale.X()),
1140 static_cast<Elem_t> (myAxialScale.Y()),
1141 static_cast<Elem_t> (myAxialScale.Z()));
b5ac8292 1142
607e5e62 1143 LookOrientation (anEye, aViewDir, anUp, anAxialScale, theMatrices.Orientation);
b5ac8292 1144
197ac94e 1145 return theMatrices; // for inline accessors
1146}
b5ac8292 1147
197ac94e 1148// =======================================================================
1149// function : InvalidateProjection
1150// purpose :
1151// =======================================================================
1152void Graphic3d_Camera::InvalidateProjection()
1153{
1154 myMatricesD.ResetProjection();
1155 myMatricesF.ResetProjection();
825aa485 1156 myWorldViewProjState.ProjectionState() = (Standard_Size)Standard_Atomic_Increment (&THE_STATE_COUNTER);
197ac94e 1157}
b5ac8292 1158
197ac94e 1159// =======================================================================
1160// function : InvalidateOrientation
1161// purpose :
1162// =======================================================================
1163void Graphic3d_Camera::InvalidateOrientation()
1164{
1165 myMatricesD.ResetOrientation();
1166 myMatricesF.ResetOrientation();
825aa485 1167 myWorldViewProjState.WorldViewState() = (Standard_Size)Standard_Atomic_Increment (&THE_STATE_COUNTER);
b5ac8292 1168}
1169
1170// =======================================================================
b40cdc2b 1171// function : orthoProj
b5ac8292 1172// purpose :
1173// =======================================================================
197ac94e 1174template <typename Elem_t>
b40cdc2b 1175void Graphic3d_Camera::orthoProj (NCollection_Mat4<Elem_t>& theOutMx,
1176 const Aspect_FrustumLRBT<Elem_t>& theLRBT,
197ac94e 1177 const Elem_t theNear,
b40cdc2b 1178 const Elem_t theFar)
b5ac8292 1179{
1180 // row 0
b40cdc2b 1181 theOutMx.ChangeValue (0, 0) = Elem_t (2.0) / (theLRBT.Right - theLRBT.Left);
197ac94e 1182 theOutMx.ChangeValue (0, 1) = Elem_t (0.0);
1183 theOutMx.ChangeValue (0, 2) = Elem_t (0.0);
b40cdc2b 1184 theOutMx.ChangeValue (0, 3) = - (theLRBT.Right + theLRBT.Left) / (theLRBT.Right - theLRBT.Left);
b5ac8292 1185
1186 // row 1
197ac94e 1187 theOutMx.ChangeValue (1, 0) = Elem_t (0.0);
b40cdc2b 1188 theOutMx.ChangeValue (1, 1) = Elem_t (2.0) / (theLRBT.Top - theLRBT.Bottom);
197ac94e 1189 theOutMx.ChangeValue (1, 2) = Elem_t (0.0);
b40cdc2b 1190 theOutMx.ChangeValue (1, 3) = - (theLRBT.Top + theLRBT.Bottom) / (theLRBT.Top - theLRBT.Bottom);
b5ac8292 1191
1192 // row 2
197ac94e 1193 theOutMx.ChangeValue (2, 0) = Elem_t (0.0);
1194 theOutMx.ChangeValue (2, 1) = Elem_t (0.0);
1195 theOutMx.ChangeValue (2, 2) = Elem_t (-2.0) / (theFar - theNear);
b5ac8292 1196 theOutMx.ChangeValue (2, 3) = - (theFar + theNear) / (theFar - theNear);
1197
1198 // row 3
197ac94e 1199 theOutMx.ChangeValue (3, 0) = Elem_t (0.0);
1200 theOutMx.ChangeValue (3, 1) = Elem_t (0.0);
1201 theOutMx.ChangeValue (3, 2) = Elem_t (0.0);
1202 theOutMx.ChangeValue (3, 3) = Elem_t (1.0);
b5ac8292 1203}
1204
1205// =======================================================================
1206// function : PerspectiveProj
1207// purpose :
1208// =======================================================================
197ac94e 1209template <typename Elem_t>
b40cdc2b 1210void Graphic3d_Camera::perspectiveProj (NCollection_Mat4<Elem_t>& theOutMx,
1211 const Aspect_FrustumLRBT<Elem_t>& theLRBT,
197ac94e 1212 const Elem_t theNear,
b40cdc2b 1213 const Elem_t theFar)
b5ac8292 1214{
1215 // column 0
b40cdc2b 1216 theOutMx.ChangeValue (0, 0) = (Elem_t (2.0) * theNear) / (theLRBT.Right - theLRBT.Left);
197ac94e 1217 theOutMx.ChangeValue (1, 0) = Elem_t (0.0);
1218 theOutMx.ChangeValue (2, 0) = Elem_t (0.0);
1219 theOutMx.ChangeValue (3, 0) = Elem_t (0.0);
b5ac8292 1220
1221 // column 1
197ac94e 1222 theOutMx.ChangeValue (0, 1) = Elem_t (0.0);
b40cdc2b 1223 theOutMx.ChangeValue (1, 1) = (Elem_t (2.0) * theNear) / (theLRBT.Top - theLRBT.Bottom);
197ac94e 1224 theOutMx.ChangeValue (2, 1) = Elem_t (0.0);
1225 theOutMx.ChangeValue (3, 1) = Elem_t (0.0);
b5ac8292 1226
1227 // column 2
b40cdc2b 1228 theOutMx.ChangeValue (0, 2) = (theLRBT.Right + theLRBT.Left) / (theLRBT.Right - theLRBT.Left);
1229 theOutMx.ChangeValue (1, 2) = (theLRBT.Top + theLRBT.Bottom) / (theLRBT.Top - theLRBT.Bottom);
b5ac8292 1230 theOutMx.ChangeValue (2, 2) = -(theFar + theNear) / (theFar - theNear);
197ac94e 1231 theOutMx.ChangeValue (3, 2) = Elem_t (-1.0);
b5ac8292 1232
1233 // column 3
197ac94e 1234 theOutMx.ChangeValue (0, 3) = Elem_t (0.0);
1235 theOutMx.ChangeValue (1, 3) = Elem_t (0.0);
1236 theOutMx.ChangeValue (2, 3) = -(Elem_t (2.0) * theFar * theNear) / (theFar - theNear);
1237 theOutMx.ChangeValue (3, 3) = Elem_t (0.0);
b5ac8292 1238}
1239
1240// =======================================================================
1241// function : StereoEyeProj
1242// purpose :
1243// =======================================================================
197ac94e 1244template <typename Elem_t>
b40cdc2b 1245void Graphic3d_Camera::stereoEyeProj (NCollection_Mat4<Elem_t>& theOutMx,
1246 const Aspect_FrustumLRBT<Elem_t>& theLRBT,
197ac94e 1247 const Elem_t theNear,
1248 const Elem_t theFar,
1249 const Elem_t theIOD,
1250 const Elem_t theZFocus,
b40cdc2b 1251 const Aspect_Eye theEyeIndex)
b5ac8292 1252{
b40cdc2b 1253 Elem_t aDx = theEyeIndex == Aspect_Eye_Left ? Elem_t (0.5) * theIOD : Elem_t (-0.5) * theIOD;
197ac94e 1254 Elem_t aDXStereoShift = aDx * theNear / theZFocus;
b5ac8292 1255
1256 // construct eye projection matrix
b40cdc2b 1257 Aspect_FrustumLRBT<Elem_t> aLRBT = theLRBT;
1258 aLRBT.Left = theLRBT.Left + aDXStereoShift;
1259 aLRBT.Right = theLRBT.Right + aDXStereoShift;
1260 perspectiveProj (theOutMx, aLRBT, theNear, theFar);
b5ac8292 1261
197ac94e 1262 if (theIOD != Elem_t (0.0))
b5ac8292 1263 {
1264 // X translation to cancel parallax
197ac94e 1265 theOutMx.Translate (NCollection_Vec3<Elem_t> (aDx, Elem_t (0.0), Elem_t (0.0)));
b5ac8292 1266 }
1267}
1268
1269// =======================================================================
1270// function : LookOrientation
1271// purpose :
1272// =======================================================================
197ac94e 1273template <typename Elem_t>
1274void Graphic3d_Camera::LookOrientation (const NCollection_Vec3<Elem_t>& theEye,
607e5e62 1275 const NCollection_Vec3<Elem_t>& theFwdDir,
197ac94e 1276 const NCollection_Vec3<Elem_t>& theUpDir,
1277 const NCollection_Vec3<Elem_t>& theAxialScale,
1278 NCollection_Mat4<Elem_t>& theOutMx)
b5ac8292 1279{
607e5e62 1280 NCollection_Vec3<Elem_t> aForward = theFwdDir;
b5ac8292 1281 aForward.Normalize();
1282
1283 // side = forward x up
197ac94e 1284 NCollection_Vec3<Elem_t> aSide = NCollection_Vec3<Elem_t>::Cross (aForward, theUpDir);
b5ac8292 1285 aSide.Normalize();
1286
1287 // recompute up as: up = side x forward
197ac94e 1288 NCollection_Vec3<Elem_t> anUp = NCollection_Vec3<Elem_t>::Cross (aSide, aForward);
b5ac8292 1289
197ac94e 1290 NCollection_Mat4<Elem_t> aLookMx;
b5ac8292 1291 aLookMx.SetRow (0, aSide);
1292 aLookMx.SetRow (1, anUp);
1293 aLookMx.SetRow (2, -aForward);
1294
197ac94e 1295 theOutMx.InitIdentity();
1296 theOutMx.Multiply (aLookMx);
b5ac8292 1297 theOutMx.Translate (-theEye);
1298
197ac94e 1299 NCollection_Mat4<Elem_t> anAxialScaleMx;
b5ac8292 1300 anAxialScaleMx.ChangeValue (0, 0) = theAxialScale.x();
1301 anAxialScaleMx.ChangeValue (1, 1) = theAxialScale.y();
1302 anAxialScaleMx.ChangeValue (2, 2) = theAxialScale.z();
1303
1304 theOutMx.Multiply (anAxialScaleMx);
1305}
6bc6a6fc 1306
1307//=============================================================================
1308//function : ZFitAll
1309//purpose :
1310//=============================================================================
10dbdf34 1311bool Graphic3d_Camera::ZFitAll (const Standard_Real theScaleFactor,
1312 const Bnd_Box& theMinMax,
1313 const Bnd_Box& theGraphicBB,
1314 Standard_Real& theZNear,
1315 Standard_Real& theZFar) const
6bc6a6fc 1316{
1317 Standard_ASSERT_RAISE (theScaleFactor > 0.0, "Zero or negative scale factor is not allowed.");
1318
ea764884 1319 // Method changes zNear and zFar parameters of camera so as to fit graphical structures
1320 // by their graphical boundaries. It precisely fits min max boundaries of primary application
1321 // objects (second argument), while it can sacrifice the real graphical boundaries of the
1322 // scene with infinite or helper objects (third argument) for the sake of perspective projection.
ed063270 1323 if (theGraphicBB.IsVoid())
6bc6a6fc 1324 {
10dbdf34 1325 theZNear = DEFAULT_ZNEAR;
1326 theZFar = DEFAULT_ZFAR;
1327 return false;
6bc6a6fc 1328 }
1329
ea764884 1330 // Measure depth of boundary points from camera eye.
ed063270 1331 NCollection_Sequence<gp_Pnt> aPntsToMeasure;
1332
ea764884 1333 Standard_Real aGraphicBB[6];
ed063270 1334 theGraphicBB.Get (aGraphicBB[0], aGraphicBB[1], aGraphicBB[2], aGraphicBB[3], aGraphicBB[4], aGraphicBB[5]);
1335
1336 aPntsToMeasure.Append (gp_Pnt (aGraphicBB[0], aGraphicBB[1], aGraphicBB[2]));
1337 aPntsToMeasure.Append (gp_Pnt (aGraphicBB[0], aGraphicBB[1], aGraphicBB[5]));
1338 aPntsToMeasure.Append (gp_Pnt (aGraphicBB[0], aGraphicBB[4], aGraphicBB[2]));
1339 aPntsToMeasure.Append (gp_Pnt (aGraphicBB[0], aGraphicBB[4], aGraphicBB[5]));
1340 aPntsToMeasure.Append (gp_Pnt (aGraphicBB[3], aGraphicBB[1], aGraphicBB[2]));
1341 aPntsToMeasure.Append (gp_Pnt (aGraphicBB[3], aGraphicBB[1], aGraphicBB[5]));
1342 aPntsToMeasure.Append (gp_Pnt (aGraphicBB[3], aGraphicBB[4], aGraphicBB[2]));
1343 aPntsToMeasure.Append (gp_Pnt (aGraphicBB[3], aGraphicBB[4], aGraphicBB[5]));
1344
5a19c303 1345 Standard_Boolean isFiniteMinMax = !theMinMax.IsVoid() && !theMinMax.IsWhole();
1346
1347 if (isFiniteMinMax)
6bc6a6fc 1348 {
ea764884 1349 Standard_Real aMinMax[6];
ed063270 1350 theMinMax.Get (aMinMax[0], aMinMax[1], aMinMax[2], aMinMax[3], aMinMax[4], aMinMax[5]);
1351
1352 aPntsToMeasure.Append (gp_Pnt (aMinMax[0], aMinMax[1], aMinMax[2]));
1353 aPntsToMeasure.Append (gp_Pnt (aMinMax[0], aMinMax[1], aMinMax[5]));
1354 aPntsToMeasure.Append (gp_Pnt (aMinMax[0], aMinMax[4], aMinMax[2]));
1355 aPntsToMeasure.Append (gp_Pnt (aMinMax[0], aMinMax[4], aMinMax[5]));
1356 aPntsToMeasure.Append (gp_Pnt (aMinMax[3], aMinMax[1], aMinMax[2]));
1357 aPntsToMeasure.Append (gp_Pnt (aMinMax[3], aMinMax[1], aMinMax[5]));
1358 aPntsToMeasure.Append (gp_Pnt (aMinMax[3], aMinMax[4], aMinMax[2]));
1359 aPntsToMeasure.Append (gp_Pnt (aMinMax[3], aMinMax[4], aMinMax[5]));
1360 }
6bc6a6fc 1361
ea764884 1362 // Camera eye plane.
6bc6a6fc 1363 gp_Dir aCamDir = Direction();
1364 gp_Pnt aCamEye = myEye;
1365 gp_Pln aCamPln (aCamEye, aCamDir);
1366
5a19c303 1367 Standard_Real aModelMinDist = RealLast();
1368 Standard_Real aModelMaxDist = RealFirst();
1369 Standard_Real aGraphMinDist = RealLast();
1370 Standard_Real aGraphMaxDist = RealFirst();
6bc6a6fc 1371
1372 const gp_XYZ& anAxialScale = myAxialScale;
1373
ea764884 1374 // Get minimum and maximum distances to the eye plane.
ed063270 1375 Standard_Integer aCounter = 0;
1376 NCollection_Sequence<gp_Pnt>::Iterator aPntIt(aPntsToMeasure);
1377 for (; aPntIt.More(); aPntIt.Next())
6bc6a6fc 1378 {
ed063270 1379 gp_Pnt aMeasurePnt = aPntIt.Value();
6bc6a6fc 1380
1381 aMeasurePnt = gp_Pnt (aMeasurePnt.X() * anAxialScale.X(),
ed063270 1382 aMeasurePnt.Y() * anAxialScale.Y(),
1383 aMeasurePnt.Z() * anAxialScale.Z());
6bc6a6fc 1384
1385 Standard_Real aDistance = aCamPln.Distance (aMeasurePnt);
1386
ea764884 1387 // Check if the camera is intruded into the scene.
607e5e62 1388 gp_Vec aVecToMeasurePnt (aCamEye, aMeasurePnt);
1389 if (aVecToMeasurePnt.Magnitude() > gp::Resolution()
1390 && aCamDir.IsOpposite (aVecToMeasurePnt, M_PI * 0.5))
6bc6a6fc 1391 {
1392 aDistance *= -1;
1393 }
1394
ea764884 1395 // The first eight points are from theGraphicBB, the last eight points are from theMinMax (can be absent).
5a19c303 1396 Standard_Real& aChangeMinDist = aCounter >= 8 ? aModelMinDist : aGraphMinDist;
1397 Standard_Real& aChangeMaxDist = aCounter >= 8 ? aModelMaxDist : aGraphMaxDist;
6bc6a6fc 1398 aChangeMinDist = Min (aDistance, aChangeMinDist);
1399 aChangeMaxDist = Max (aDistance, aChangeMaxDist);
ed063270 1400 aCounter++;
6bc6a6fc 1401 }
1402
ea764884 1403 // Compute depth of bounding box center.
5a19c303 1404 Standard_Real aMidDepth = (aGraphMinDist + aGraphMaxDist) * 0.5;
1405 Standard_Real aHalfDepth = (aGraphMaxDist - aGraphMinDist) * 0.5;
6bc6a6fc 1406
ea764884 1407 // Compute enlarged or shrank near and far z ranges.
35c4a17c 1408 Standard_Real aZNear = aMidDepth - aHalfDepth * theScaleFactor;
1409 Standard_Real aZFar = aMidDepth + aHalfDepth * theScaleFactor;
6bc6a6fc 1410
1411 if (!IsOrthographic())
1412 {
ea764884 1413 // Everything is behind the perspective camera.
1414 if (aZFar < zEpsilon())
6bc6a6fc 1415 {
10dbdf34 1416 theZNear = DEFAULT_ZNEAR;
1417 theZFar = DEFAULT_ZFAR;
1418 return false;
6bc6a6fc 1419 }
6bc6a6fc 1420 }
1421
ea764884 1422 //
1423 // Consider clipping errors due to double to single precision floating-point conversion.
1424 //
1425
1426 // Model to view transformation performs translation of points against eye position
1427 // in three dimensions. Both point coordinate and eye position values are converted from
1428 // double to single precision floating point numbers producing conversion errors.
1429 // Epsilon (Mod) * 3.0 should safely compensate precision error for z coordinate after
1430 // translation assuming that the:
1431 // Epsilon (Eye.Mod()) * 3.0 > Epsilon (Eye.X()) + Epsilon (Eye.Y()) + Epsilon (Eye.Z()).
1432 Standard_Real aEyeConf = 3.0 * zEpsilon (myEye.XYZ().Modulus());
1433
1434 // Model to view transformation performs rotation of points according to view direction.
1435 // New z coordinate is computed as a multiplication of point's x, y, z coordinates by the
1436 // "forward" direction vector's x, y, z coordinates. Both point's and "z" direction vector's
1437 // values are converted from double to single precision floating point numbers producing
1438 // conversion errors.
1439 // Epsilon (Mod) * 6.0 should safely compensate the precision errors for the multiplication
1440 // of point coordinates by direction vector.
1441 gp_Pnt aGraphicMin = theGraphicBB.CornerMin();
1442 gp_Pnt aGraphicMax = theGraphicBB.CornerMax();
1443
1444 Standard_Real aModelConf = 6.0 * zEpsilon (aGraphicMin.XYZ().Modulus()) +
1445 6.0 * zEpsilon (aGraphicMax.XYZ().Modulus());
1446
1447 // Compensate floating point conversion errors by increasing zNear, zFar to avoid clipping.
1448 aZNear -= zEpsilon (aZNear) + aEyeConf + aModelConf;
1449 aZFar += zEpsilon (aZFar) + aEyeConf + aModelConf;
1450
1451 if (!IsOrthographic())
6bc6a6fc 1452 {
5a19c303 1453 // For perspective projection, the value of z in normalized device coordinates is non-linear
1454 // function of eye z coordinate. For fixed-point depth representation resolution of z in
1455 // model-view space will grow towards zFar plane and its scale depends mostly on how far is zNear
1456 // against camera's eye. The purpose of the code below is to select most appropriate zNear distance
1457 // to balance between clipping (less zNear, more chances to observe closely small models without clipping)
1458 // and resolution of depth. A well applicable criteria to this is a ratio between resolution of z at center
1459 // of model boundaries and the distance to that center point. The ratio is chosen empirically and validated
1460 // by tests database. It is considered to be ~0.001 (0.1%) for 24 bit depth buffer, for less depth bitness
1461 // the zNear will be placed similarly giving lower resolution.
1462 // Approximation of the formula for respectively large z range is:
1463 // zNear = [z * (1 + k) / (k * c)],
1464 // where:
1465 // z - distance to center of model boundaries;
1466 // k - chosen ratio, c - capacity of depth buffer;
1467 // k = 0.001, k * c = 1677.216, (1 + k) / (k * c) ~ 5.97E-4
1468 //
1469 // The function uses center of model boundaries computed from "theMinMax" boundaries (instead of using real
1470 // graphical boundaries of all displayed objects). That means that it can sacrifice resolution of presentation
1471 // of non primary ("infinite") application graphical objects in favor of better perspective projection of the
1472 // small applicative objects measured with "theMinMax" values.
1473 Standard_Real aZRange = isFiniteMinMax ? aModelMaxDist - aModelMinDist : aGraphMaxDist - aGraphMinDist;
1474 Standard_Real aZMin = isFiniteMinMax ? aModelMinDist : aGraphMinDist;
1475 Standard_Real aZ = aZMin < 0 ? aZRange / 2.0 : aZRange / 2.0 + aZMin;
1476 Standard_Real aZNearMin = aZ * 5.97E-4;
1477 if (aZNear < aZNearMin)
1478 {
1479 // Clip zNear according to the minimum value matching the quality.
1480 aZNear = aZNearMin;
607e5e62 1481 if (aZFar < aZNear)
1482 {
1483 aZFar = aZNear;
1484 }
5a19c303 1485 }
1486 else
1487 {
1488 // Compensate zNear conversion errors for perspective projection.
1489 aZNear -= aZFar * zEpsilon (aZNear) / (aZFar - zEpsilon (aZNear));
1490 }
1491
1492 // Compensate zFar conversion errors for perspective projection.
1493 aZFar += zEpsilon (aZFar);
ea764884 1494
1495 // Ensure that after all the zNear is not a negative value.
1496 if (aZNear < zEpsilon())
1497 {
1498 aZNear = zEpsilon();
1499 }
607e5e62 1500 Standard_ASSERT_RAISE (aZFar > aZNear, "ZFar should be greater than ZNear");
6bc6a6fc 1501 }
1502
10dbdf34 1503 theZNear = aZNear;
1504 theZFar = aZFar;
607e5e62 1505 Standard_ASSERT_RAISE (aZFar > aZNear, "ZFar should be greater than ZNear");
10dbdf34 1506 return true;
6bc6a6fc 1507}
1beb58d7 1508
1509//=============================================================================
1510//function : Interpolate
1511//purpose :
1512//=============================================================================
1513template<>
1514Standard_EXPORT void NCollection_Lerp<Handle(Graphic3d_Camera)>::Interpolate (const double theT,
1515 Handle(Graphic3d_Camera)& theCamera) const
1516{
1517 if (Abs (theT - 1.0) < Precision::Confusion())
1518 {
1519 // just copy end-point transformation
1520 theCamera->Copy (myEnd);
1521 return;
1522 }
1523
1524 theCamera->Copy (myStart);
1525 if (Abs (theT - 0.0) < Precision::Confusion())
1526 {
1527 return;
1528 }
1529
1530 // apply rotation
1531 {
1532 gp_Ax3 aCamStart = cameraToAx3 (*myStart);
1533 gp_Ax3 aCamEnd = cameraToAx3 (*myEnd);
1534 gp_Trsf aTrsfStart, aTrsfEnd;
1535 aTrsfStart.SetTransformation (aCamStart, gp::XOY());
1536 aTrsfEnd .SetTransformation (aCamEnd, gp::XOY());
1537
1538 gp_Quaternion aRotStart = aTrsfStart.GetRotation();
1539 gp_Quaternion aRotEnd = aTrsfEnd .GetRotation();
1540 gp_Quaternion aRotDelta = aRotEnd * aRotStart.Inverted();
1541 gp_Quaternion aRot = gp_QuaternionNLerp::Interpolate (gp_Quaternion(), aRotDelta, theT);
1542 gp_Trsf aTrsfRot;
1543 aTrsfRot.SetRotation (aRot);
1544 theCamera->Transform (aTrsfRot);
1545 }
1546
1547 // apply translation
1548 {
1549 gp_XYZ aCenter = NCollection_Lerp<gp_XYZ>::Interpolate (myStart->Center().XYZ(), myEnd->Center().XYZ(), theT);
1550 gp_XYZ anEye = NCollection_Lerp<gp_XYZ>::Interpolate (myStart->Eye().XYZ(), myEnd->Eye().XYZ(), theT);
1551 gp_XYZ anAnchor = aCenter;
1552 Standard_Real aKc = 0.0;
1553
1554 const Standard_Real aDeltaCenter = myStart->Center().Distance (myEnd->Center());
1555 const Standard_Real aDeltaEye = myStart->Eye() .Distance (myEnd->Eye());
1556 if (aDeltaEye <= gp::Resolution())
1557 {
1558 anAnchor = anEye;
1559 aKc = 1.0;
1560 }
1561 else if (aDeltaCenter > gp::Resolution())
1562 {
1563 aKc = aDeltaCenter / (aDeltaCenter + aDeltaEye);
1564
1565 const gp_XYZ anAnchorStart = NCollection_Lerp<gp_XYZ>::Interpolate (myStart->Center().XYZ(), myStart->Eye().XYZ(), aKc);
1566 const gp_XYZ anAnchorEnd = NCollection_Lerp<gp_XYZ>::Interpolate (myEnd ->Center().XYZ(), myEnd ->Eye().XYZ(), aKc);
1567 anAnchor = NCollection_Lerp<gp_XYZ>::Interpolate (anAnchorStart, anAnchorEnd, theT);
1568 }
1569
1570 const gp_Vec aDirEyeToCenter = theCamera->Direction();
1571 const Standard_Real aDistEyeCenterStart = myStart->Eye().Distance (myStart->Center());
1572 const Standard_Real aDistEyeCenterEnd = myEnd ->Eye().Distance (myEnd ->Center());
1573 const Standard_Real aDistEyeCenter = NCollection_Lerp<Standard_Real>::Interpolate (aDistEyeCenterStart, aDistEyeCenterEnd, theT);
1574 aCenter = anAnchor + aDirEyeToCenter.XYZ() * aDistEyeCenter * aKc;
1575 anEye = anAnchor - aDirEyeToCenter.XYZ() * aDistEyeCenter * (1.0 - aKc);
1576
607e5e62 1577 theCamera->SetEyeAndCenter (anEye, aCenter);
1beb58d7 1578 }
1579
1580 // apply scaling
1581 if (Abs(myStart->Scale() - myEnd->Scale()) > Precision::Confusion()
1582 && myStart->IsOrthographic())
1583 {
1584 const Standard_Real aScale = NCollection_Lerp<Standard_Real>::Interpolate (myStart->Scale(), myEnd->Scale(), theT);
1585 theCamera->SetScale (aScale);
1586 }
1587}
30a1b24e 1588
1589//=======================================================================
1590//function : FrustumPoints
1591//purpose :
1592//=======================================================================
9ad4ff93 1593void Graphic3d_Camera::FrustumPoints (NCollection_Array1<Graphic3d_Vec3d>& thePoints,
1594 const Graphic3d_Mat4d& theModelWorld) const
30a1b24e 1595{
1596 if (thePoints.Length() != FrustumVerticesNB)
1597 {
1598 thePoints.Resize (0, FrustumVerticesNB, Standard_False);
1599 }
1600
1601 const Graphic3d_Mat4d& aProjectionMat = ProjectionMatrix();
9ad4ff93 1602 const Graphic3d_Mat4d aWorldViewMat = OrientationMatrix() * theModelWorld;
30a1b24e 1603
1604 Standard_Real nLeft = 0.0, nRight = 0.0, nTop = 0.0, nBottom = 0.0;
1605 Standard_Real fLeft = 0.0, fRight = 0.0, fTop = 0.0, fBottom = 0.0;
1606 Standard_Real aNear = 0.0, aFar = 0.0;
1607 if (!IsOrthographic())
1608 {
1609 // handle perspective projection
1610 aNear = aProjectionMat.GetValue (2, 3) / (-1.0 + aProjectionMat.GetValue (2, 2));
1611 aFar = aProjectionMat.GetValue (2, 3) / ( 1.0 + aProjectionMat.GetValue (2, 2));
1612 // Near plane
1613 nLeft = aNear * (aProjectionMat.GetValue (0, 2) - 1.0) / aProjectionMat.GetValue (0, 0);
1614 nRight = aNear * (aProjectionMat.GetValue (0, 2) + 1.0) / aProjectionMat.GetValue (0, 0);
1615 nTop = aNear * (aProjectionMat.GetValue (1, 2) + 1.0) / aProjectionMat.GetValue (1, 1);
1616 nBottom = aNear * (aProjectionMat.GetValue (1, 2) - 1.0) / aProjectionMat.GetValue (1, 1);
1617 // Far plane
1618 fLeft = aFar * (aProjectionMat.GetValue (0, 2) - 1.0) / aProjectionMat.GetValue (0, 0);
1619 fRight = aFar * (aProjectionMat.GetValue (0, 2) + 1.0) / aProjectionMat.GetValue (0, 0);
1620 fTop = aFar * (aProjectionMat.GetValue (1, 2) + 1.0) / aProjectionMat.GetValue (1, 1);
1621 fBottom = aFar * (aProjectionMat.GetValue (1, 2) - 1.0) / aProjectionMat.GetValue (1, 1);
1622 }
1623 else
1624 {
1625 // handle orthographic projection
1626 aNear = (1.0 / aProjectionMat.GetValue (2, 2)) * (aProjectionMat.GetValue (2, 3) + 1.0);
1627 aFar = (1.0 / aProjectionMat.GetValue (2, 2)) * (aProjectionMat.GetValue (2, 3) - 1.0);
1628 // Near plane
1629 nLeft = ( 1.0 + aProjectionMat.GetValue (0, 3)) / (-aProjectionMat.GetValue (0, 0));
1630 fLeft = nLeft;
1631 nRight = ( 1.0 - aProjectionMat.GetValue (0, 3)) / aProjectionMat.GetValue (0, 0);
1632 fRight = nRight;
1633 nTop = ( 1.0 - aProjectionMat.GetValue (1, 3)) / aProjectionMat.GetValue (1, 1);
1634 fTop = nTop;
1635 nBottom = (-1.0 - aProjectionMat.GetValue (1, 3)) / aProjectionMat.GetValue (1, 1);
1636 fBottom = nBottom;
1637 }
1638
1639 Graphic3d_Vec4d aLeftTopNear (nLeft, nTop, -aNear, 1.0), aRightBottomFar (fRight, fBottom, -aFar, 1.0);
1640 Graphic3d_Vec4d aLeftBottomNear (nLeft, nBottom, -aNear, 1.0), aRightTopFar (fRight, fTop, -aFar, 1.0);
1641 Graphic3d_Vec4d aRightBottomNear (nRight, nBottom, -aNear, 1.0), aLeftTopFar (fLeft, fTop, -aFar, 1.0);
1642 Graphic3d_Vec4d aRightTopNear (nRight, nTop, -aNear, 1.0), aLeftBottomFar (fLeft, fBottom, -aFar, 1.0);
1643
1644 Graphic3d_Mat4d anInvWorldView;
1645 aWorldViewMat.Inverted (anInvWorldView);
1646
1647 Graphic3d_Vec4d aTmpPnt;
1648 aTmpPnt = anInvWorldView * aLeftTopNear;
1649 thePoints.SetValue (FrustumVert_LeftTopNear, aTmpPnt.xyz() / aTmpPnt.w());
1650 aTmpPnt = anInvWorldView * aRightBottomFar;
1651 thePoints.SetValue (FrustumVert_RightBottomFar, aTmpPnt.xyz() / aTmpPnt.w());
1652 aTmpPnt = anInvWorldView * aLeftBottomNear;
1653 thePoints.SetValue (FrustumVert_LeftBottomNear, aTmpPnt.xyz() / aTmpPnt.w());
1654 aTmpPnt = anInvWorldView * aRightTopFar;
1655 thePoints.SetValue (FrustumVert_RightTopFar, aTmpPnt.xyz() / aTmpPnt.w());
1656 aTmpPnt = anInvWorldView * aRightBottomNear;
1657 thePoints.SetValue (FrustumVert_RightBottomNear, aTmpPnt.xyz() / aTmpPnt.w());
1658 aTmpPnt = anInvWorldView * aLeftTopFar;
1659 thePoints.SetValue (FrustumVert_LeftTopFar, aTmpPnt.xyz() / aTmpPnt.w());
1660 aTmpPnt = anInvWorldView * aRightTopNear;
1661 thePoints.SetValue (FrustumVert_RightTopNear, aTmpPnt.xyz() / aTmpPnt.w());
1662 aTmpPnt = anInvWorldView * aLeftBottomFar;
1663 thePoints.SetValue (FrustumVert_LeftBottomFar, aTmpPnt.xyz() / aTmpPnt.w());
1664}
bc73b006 1665
1666//=======================================================================
1667//function : DumpJson
1668//purpose :
1669//=======================================================================
1670void Graphic3d_Camera::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const
1671{
1672 OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
1673
1674 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myUp)
1675 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myDirection)
1676 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myEye)
1677
1678 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myDistance)
1679}