0025071: Visualization - Inconsistent deflection values used by AIS_Shape
[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
25IMPLEMENT_STANDARD_HANDLE(Graphic3d_Camera, Standard_Transient)
26IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_Camera, Standard_Transient)
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);
b5ac8292 42};
43
44// =======================================================================
45// function : Graphic3d_Camera
46// purpose :
47// =======================================================================
48Graphic3d_Camera::Graphic3d_Camera()
49: myUp (0.0, 1.0, 0.0),
50 myEye (0.0, 0.0, -1500.0),
51 myCenter (0.0, 0.0, 0.0),
b5ac8292 52 myAxialScale (1.0, 1.0, 1.0),
53 myProjType (Projection_Orthographic),
54 myFOVy (45.0),
197ac94e 55 myZNear (DEFAULT_ZNEAR),
56 myZFar (DEFAULT_ZFAR),
b5ac8292 57 myAspect (1.0),
58 myScale (1000.0),
59 myZFocus (1.0),
60 myZFocusType (FocusType_Relative),
61 myIOD (0.05),
197ac94e 62 myIODType (IODType_Relative)
b5ac8292 63{
64 myProjectionState = (Standard_Size)Standard_Atomic_Increment (&THE_STATE_COUNTER);
65 myOrientationState = (Standard_Size)Standard_Atomic_Increment (&THE_STATE_COUNTER);
b5ac8292 66}
67
68// =======================================================================
69// function : Graphic3d_Camera
70// purpose :
71// =======================================================================
72Graphic3d_Camera::Graphic3d_Camera (const Handle(Graphic3d_Camera)& theOther)
b5ac8292 73{
74 Copy (theOther);
75}
76
77// =======================================================================
78// function : CopyMappingData
79// purpose :
80// =======================================================================
81void Graphic3d_Camera::CopyMappingData (const Handle(Graphic3d_Camera)& theOtherCamera)
82{
197ac94e 83 myFOVy = theOtherCamera->myFOVy;
84 myZNear = theOtherCamera->myZNear;
85 myZFar = theOtherCamera->myZFar;
86 myAspect = theOtherCamera->myAspect;
87 myScale = theOtherCamera->myScale;
88 myZFocus = theOtherCamera->myZFocus;
89 myZFocusType = theOtherCamera->myZFocusType;
90 myIOD = theOtherCamera->myIOD;
91 myIODType = theOtherCamera->myIODType;
92 myProjType = theOtherCamera->myProjType;
93 myProjectionState = theOtherCamera->myProjectionState;
b5ac8292 94
197ac94e 95 InvalidateProjection();
b5ac8292 96}
97
98// =======================================================================
99// function : CopyOrientationData
100// purpose :
101// =======================================================================
102void Graphic3d_Camera::CopyOrientationData (const Handle(Graphic3d_Camera)& theOtherCamera)
103{
197ac94e 104 myUp = theOtherCamera->myUp;
105 myEye = theOtherCamera->myEye;
106 myCenter = theOtherCamera->myCenter;
107 myAxialScale = theOtherCamera->myAxialScale;
b5ac8292 108 myOrientationState = theOtherCamera->myOrientationState;
109
197ac94e 110 InvalidateOrientation();
b5ac8292 111}
112
113// =======================================================================
114// function : Copy
115// purpose :
116// =======================================================================
117void Graphic3d_Camera::Copy (const Handle(Graphic3d_Camera)& theOther)
118{
b5ac8292 119 CopyMappingData (theOther);
120 CopyOrientationData (theOther);
b5ac8292 121}
122
123// =======================================================================
124// function : SetEye
125// purpose :
126// =======================================================================
127void Graphic3d_Camera::SetEye (const gp_Pnt& theEye)
128{
129 myEye = theEye;
197ac94e 130 InvalidateOrientation();
b5ac8292 131}
132
133// =======================================================================
134// function : SetCenter
135// purpose :
136// =======================================================================
137void Graphic3d_Camera::SetCenter (const gp_Pnt& theCenter)
138{
139 myCenter = theCenter;
197ac94e 140 InvalidateOrientation();
b5ac8292 141}
142
143// =======================================================================
144// function : SetUp
145// purpose :
146// =======================================================================
147void Graphic3d_Camera::SetUp (const gp_Dir& theUp)
148{
149 myUp = theUp;
197ac94e 150 InvalidateOrientation();
b5ac8292 151}
152
153// =======================================================================
154// function : SetAxialScale
155// purpose :
156// =======================================================================
197ac94e 157void Graphic3d_Camera::SetAxialScale (const gp_XYZ& theAxialScale)
b5ac8292 158{
159 myAxialScale = theAxialScale;
197ac94e 160 InvalidateOrientation();
b5ac8292 161}
162
163// =======================================================================
164// function : SetDistance
165// purpose :
166// =======================================================================
167void Graphic3d_Camera::SetDistance (const Standard_Real theDistance)
168{
169 gp_Vec aCenter2Eye (Direction());
170 aCenter2Eye.Reverse();
3c648527 171
172 // Camera should have non-zero distance.
173 aCenter2Eye.Scale (Max (theDistance, MIN_DISTANCE));
b5ac8292 174 SetEye (Center().Translated (aCenter2Eye));
175}
176
177// =======================================================================
178// function : Distance
179// purpose :
180// =======================================================================
181Standard_Real Graphic3d_Camera::Distance() const
182{
183 return myEye.Distance (myCenter);
184}
185
186// =======================================================================
187// function : SetDirection
188// purpose :
189// =======================================================================
190void Graphic3d_Camera::SetDirection (const gp_Dir& theDir)
191{
192 gp_Vec aScaledDir (theDir);
193 aScaledDir.Scale (Distance());
194 aScaledDir.Reverse();
195 SetEye (Center().Translated (aScaledDir));
196}
197
198// =======================================================================
199// function : Direction
200// purpose :
201// =======================================================================
202gp_Dir Graphic3d_Camera::Direction() const
203{
204 return gp_Dir (gp_Vec (myEye, myCenter));
205}
206
207// =======================================================================
208// function : SetScale
209// purpose :
210// =======================================================================
211void Graphic3d_Camera::SetScale (const Standard_Real theScale)
212{
213 myScale = theScale;
214
215 switch (myProjType)
216 {
217 case Projection_Perspective :
218 case Projection_Stereo :
219 case Projection_MonoLeftEye :
220 case Projection_MonoRightEye :
221 {
222 Standard_Real aDistance = theScale * 0.5 / Tan(myFOVy * M_PI / 360.0);
223 SetDistance (aDistance);
224 }
225
226 default :
227 break;
228 }
229
197ac94e 230 InvalidateProjection();
b5ac8292 231}
232
233// =======================================================================
234// function : Scale
235// purpose :
236// =======================================================================
237Standard_Real Graphic3d_Camera::Scale() const
238{
239 switch (myProjType)
240 {
241 case Projection_Orthographic :
242 return myScale;
243
244 // case Projection_Perspective :
245 // case Projection_Stereo :
246 // case Projection_MonoLeftEye :
247 // case Projection_MonoRightEye :
248 default :
197ac94e 249 return Distance() * 2.0 * Tan (myFOVy * M_PI / 360.0);
b5ac8292 250 }
251}
252
253// =======================================================================
254// function : SetProjectionType
255// purpose :
256// =======================================================================
257void Graphic3d_Camera::SetProjectionType (const Projection theProjectionType)
258{
259 Projection anOldType = myProjType;
260
261 if (anOldType == theProjectionType)
262 {
263 return;
264 }
265
197ac94e 266 if (anOldType == Projection_Orthographic)
b5ac8292 267 {
197ac94e 268 if (myZNear <= RealEpsilon())
269 {
270 myZNear = DEFAULT_ZNEAR;
271 }
272 if (myZFar <= RealEpsilon())
273 {
274 myZFar = DEFAULT_ZFAR;
275 }
b5ac8292 276 }
277
197ac94e 278 myProjType = theProjectionType;
279
280 InvalidateProjection();
b5ac8292 281}
282
283// =======================================================================
284// function : SetFOVy
285// purpose :
286// =======================================================================
287void Graphic3d_Camera::SetFOVy (const Standard_Real theFOVy)
288{
289 myFOVy = theFOVy;
197ac94e 290 InvalidateProjection();
b5ac8292 291}
292
293// =======================================================================
197ac94e 294// function : SetZRange
b5ac8292 295// purpose :
296// =======================================================================
197ac94e 297void Graphic3d_Camera::SetZRange (const Standard_Real theZNear,
298 const Standard_Real theZFar)
b5ac8292 299{
197ac94e 300 Standard_ASSERT_RAISE (theZFar > theZNear, "ZFar should be greater than ZNear");
301 if (!IsOrthographic())
b5ac8292 302 {
197ac94e 303 Standard_ASSERT_RAISE (theZNear > 0.0, "Only positive Z-Near is allowed for perspective camera");
304 Standard_ASSERT_RAISE (theZFar > 0.0, "Only positive Z-Far is allowed for perspective camera");
b5ac8292 305 }
306
197ac94e 307 myZNear = theZNear;
308 myZFar = theZFar;
b5ac8292 309
197ac94e 310 InvalidateProjection();
b5ac8292 311}
312
313// =======================================================================
314// function : SetAspect
315// purpose :
316// =======================================================================
317void Graphic3d_Camera::SetAspect (const Standard_Real theAspect)
318{
319 myAspect = theAspect;
197ac94e 320 InvalidateProjection();
b5ac8292 321}
322
323// =======================================================================
324// function : SetZFocus
325// purpose :
326// =======================================================================
327void Graphic3d_Camera::SetZFocus(const FocusType theType, const Standard_Real theZFocus)
328{
329 myZFocusType = theType;
330 myZFocus = theZFocus;
197ac94e 331 InvalidateProjection();
b5ac8292 332}
333
334// =======================================================================
335// function : SetIOD
336// purpose :
337// =======================================================================
338void Graphic3d_Camera::SetIOD (const IODType theType, const Standard_Real theIOD)
339{
340 myIODType = theType;
341 myIOD = theIOD;
197ac94e 342 InvalidateProjection();
b5ac8292 343}
344
345// =======================================================================
346// function : OrthogonalizeUp
347// purpose :
348// =======================================================================
349void Graphic3d_Camera::OrthogonalizeUp()
350{
197ac94e 351 SetUp (OrthogonalizedUp());
b5ac8292 352}
353
354// =======================================================================
197ac94e 355// function : OrthogonalizedUp
b5ac8292 356// purpose :
357// =======================================================================
197ac94e 358gp_Dir Graphic3d_Camera::OrthogonalizedUp() const
b5ac8292 359{
197ac94e 360 gp_Dir aDir = Direction();
361 gp_Dir aLeft = aDir.Crossed (Up());
b5ac8292 362
197ac94e 363 // recompute up as: up = left x direction
364 return aLeft.Crossed (aDir);
b5ac8292 365}
366
367// =======================================================================
368// function : Transform
369// purpose :
370// =======================================================================
371void Graphic3d_Camera::Transform (const gp_Trsf& theTrsf)
372{
373 myUp.Transform (theTrsf);
374 myEye.Transform (theTrsf);
375 myCenter.Transform (theTrsf);
197ac94e 376 InvalidateOrientation();
b5ac8292 377}
378
379// =======================================================================
380// function : safePointCast
381// purpose :
382// =======================================================================
197ac94e 383static Graphic3d_Vec4d safePointCast (const gp_Pnt& thePnt)
b5ac8292 384{
385 Standard_Real aLim = 1e15f;
197ac94e 386
b5ac8292 387 // have to deal with values greater then max float
388 gp_Pnt aSafePoint = thePnt;
389 const Standard_Real aBigFloat = aLim * 0.1f;
390 if (Abs (aSafePoint.X()) > aLim)
391 aSafePoint.SetX (aSafePoint.X() >= 0 ? aBigFloat : -aBigFloat);
392 if (Abs (aSafePoint.Y()) > aLim)
393 aSafePoint.SetY (aSafePoint.Y() >= 0 ? aBigFloat : -aBigFloat);
394 if (Abs (aSafePoint.Z()) > aLim)
395 aSafePoint.SetZ (aSafePoint.Z() >= 0 ? aBigFloat : -aBigFloat);
396
397 // convert point
197ac94e 398 Graphic3d_Vec4d aPnt (aSafePoint.X(), aSafePoint.Y(), aSafePoint.Z(), 1.0);
b5ac8292 399
400 return aPnt;
401}
402
403// =======================================================================
404// function : Project
405// purpose :
406// =======================================================================
407gp_Pnt Graphic3d_Camera::Project (const gp_Pnt& thePnt) const
408{
197ac94e 409 const Graphic3d_Mat4d& aViewMx = OrientationMatrix();
410 const Graphic3d_Mat4d& aProjMx = ProjectionMatrix();
b5ac8292 411
412 // use compatible type of point
197ac94e 413 Graphic3d_Vec4d aPnt = safePointCast (thePnt);
b5ac8292 414
415 aPnt = aViewMx * aPnt; // convert to view coordinate space
416 aPnt = aProjMx * aPnt; // convert to projection coordinate space
417
418 const Standard_Real aInvW = 1.0 / Standard_Real (aPnt.w());
419
420 return gp_Pnt (aPnt.x() * aInvW, aPnt.y() * aInvW, aPnt.z() * aInvW);
421}
422
423// =======================================================================
424// function : UnProject
425// purpose :
426// =======================================================================
427gp_Pnt Graphic3d_Camera::UnProject (const gp_Pnt& thePnt) const
428{
197ac94e 429 const Graphic3d_Mat4d& aViewMx = OrientationMatrix();
430 const Graphic3d_Mat4d& aProjMx = ProjectionMatrix();
b5ac8292 431
197ac94e 432 Graphic3d_Mat4d aInvView;
433 Graphic3d_Mat4d aInvProj;
b5ac8292 434
435 // this case should never happen
436 if (!aViewMx.Inverted (aInvView) || !aProjMx.Inverted (aInvProj))
437 {
438 return gp_Pnt (0.0, 0.0, 0.0);
439 }
440
441 // use compatible type of point
197ac94e 442 Graphic3d_Vec4d aPnt = safePointCast (thePnt);
b5ac8292 443
444 aPnt = aInvProj * aPnt; // convert to view coordinate space
445 aPnt = aInvView * aPnt; // convert to world coordinate space
446
447 const Standard_Real aInvW = 1.0 / Standard_Real (aPnt.w());
448
449 return gp_Pnt (aPnt.x() * aInvW, aPnt.y() * aInvW, aPnt.z() * aInvW);
450}
451
452// =======================================================================
453// function : ConvertView2Proj
454// purpose :
455// =======================================================================
456gp_Pnt Graphic3d_Camera::ConvertView2Proj (const gp_Pnt& thePnt) const
457{
197ac94e 458 const Graphic3d_Mat4d& aProjMx = ProjectionMatrix();
b5ac8292 459
460 // use compatible type of point
197ac94e 461 Graphic3d_Vec4d aPnt = safePointCast (thePnt);
b5ac8292 462
463 aPnt = aProjMx * aPnt; // convert to projection 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 : ConvertProj2View
472// purpose :
473// =======================================================================
474gp_Pnt Graphic3d_Camera::ConvertProj2View (const gp_Pnt& thePnt) const
475{
197ac94e 476 const Graphic3d_Mat4d& aProjMx = ProjectionMatrix();
b5ac8292 477
197ac94e 478 Graphic3d_Mat4d aInvProj;
b5ac8292 479
480 // this case should never happen, but...
481 if (!aProjMx.Inverted (aInvProj))
482 {
197ac94e 483 return gp_Pnt (0, 0, 0);
b5ac8292 484 }
485
486 // use compatible type of point
197ac94e 487 Graphic3d_Vec4d aPnt = safePointCast (thePnt);
b5ac8292 488
489 aPnt = aInvProj * aPnt; // convert to view coordinate space
490
491 const Standard_Real aInvW = 1.0 / Standard_Real (aPnt.w());
492
493 return gp_Pnt (aPnt.x() * aInvW, aPnt.y() * aInvW, aPnt.z() * aInvW);
494}
495
496// =======================================================================
497// function : ConvertWorld2View
498// purpose :
499// =======================================================================
500gp_Pnt Graphic3d_Camera::ConvertWorld2View (const gp_Pnt& thePnt) const
501{
197ac94e 502 const Graphic3d_Mat4d& aViewMx = OrientationMatrix();
b5ac8292 503
504 // use compatible type of point
197ac94e 505 Graphic3d_Vec4d aPnt = safePointCast (thePnt);
b5ac8292 506
507 aPnt = aViewMx * 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 : ConvertView2World
516// purpose :
517// =======================================================================
518gp_Pnt Graphic3d_Camera::ConvertView2World (const gp_Pnt& thePnt) const
519{
197ac94e 520 const Graphic3d_Mat4d& aViewMx = OrientationMatrix();
b5ac8292 521
197ac94e 522 Graphic3d_Mat4d aInvView;
b5ac8292 523
524 if (!aViewMx.Inverted (aInvView))
525 {
526 return gp_Pnt(0, 0, 0);
527 }
528
529 // use compatible type of point
197ac94e 530 Graphic3d_Vec4d aPnt = safePointCast (thePnt);
b5ac8292 531
532 aPnt = aInvView * aPnt; // convert to world coordinate space
533
534 const Standard_Real aInvW = 1.0 / Standard_Real (aPnt.w());
535
536 return gp_Pnt (aPnt.x() * aInvW, aPnt.y() * aInvW, aPnt.z() * aInvW);
537}
538
539// =======================================================================
540// function : ViewDimensions
541// purpose :
542// =======================================================================
197ac94e 543gp_XYZ Graphic3d_Camera::ViewDimensions() const
b5ac8292 544{
545 // view plane dimensions
546 Standard_Real aSizeY = IsOrthographic() ? myScale : (2.0 * Distance() * Tan (DTR_HALF * myFOVy));
547 Standard_Real aSizeX = myAspect * aSizeY;
548
549 // and frustum depth
197ac94e 550 return gp_XYZ (aSizeX, aSizeY, myZFar - myZNear);
b5ac8292 551}
552
553// =======================================================================
197ac94e 554// function : Frustum
b5ac8292 555// purpose :
556// =======================================================================
197ac94e 557void Graphic3d_Camera::Frustum (gp_Pln& theLeft,
558 gp_Pln& theRight,
559 gp_Pln& theBottom,
560 gp_Pln& theTop,
561 gp_Pln& theNear,
562 gp_Pln& theFar) const
b5ac8292 563{
197ac94e 564 gp_Vec aProjection = gp_Vec (Direction());
565 gp_Vec anUp = OrthogonalizedUp();
566 gp_Vec aSide = aProjection ^ anUp;
567
568 Standard_ASSERT_RAISE (
569 !aProjection.IsParallel (anUp, Precision::Angular()),
570 "Can not derive SIDE = PROJ x UP - directions are parallel");
571
572 theNear = gp_Pln (Eye().Translated (aProjection * ZNear()), aProjection);
573 theFar = gp_Pln (Eye().Translated (aProjection * ZFar()), -aProjection);
574
575 Standard_Real aHScaleHor = Scale() * 0.5 * Aspect();
576 Standard_Real aHScaleVer = Scale() * 0.5;
577
578 gp_Pnt aPntLeft = Center().Translated (aHScaleHor * -aSide);
579 gp_Pnt aPntRight = Center().Translated (aHScaleHor * aSide);
580 gp_Pnt aPntBottom = Center().Translated (aHScaleVer * -anUp);
581 gp_Pnt aPntTop = Center().Translated (aHScaleVer * anUp);
582
583 gp_Vec aDirLeft = aSide;
584 gp_Vec aDirRight = -aSide;
585 gp_Vec aDirBottom = anUp;
586 gp_Vec aDirTop = -anUp;
587 if (!IsOrthographic())
588 {
589 Standard_Real aHFOVHor = ATan (Tan (DTR_HALF * FOVy()) * Aspect());
590 Standard_Real aHFOVVer = DTR_HALF * FOVy();
591 aDirLeft.Rotate (gp_Ax1 (gp::Origin(), anUp), aHFOVHor);
592 aDirRight.Rotate (gp_Ax1 (gp::Origin(), anUp), -aHFOVHor);
593 aDirBottom.Rotate (gp_Ax1 (gp::Origin(), aSide), -aHFOVVer);
594 aDirTop.Rotate (gp_Ax1 (gp::Origin(), aSide), aHFOVVer);
595 }
596
597 theLeft = gp_Pln (aPntLeft, aDirLeft);
598 theRight = gp_Pln (aPntRight, aDirRight);
599 theBottom = gp_Pln (aPntBottom, aDirBottom);
600 theTop = gp_Pln (aPntTop, aDirTop);
601}
602
603// =======================================================================
604// function : OrientationMatrix
605// purpose :
606// =======================================================================
607const Graphic3d_Mat4d& Graphic3d_Camera::OrientationMatrix() const
608{
609 return *UpdateOrientation (myMatricesD).Orientation;
610}
611
612// =======================================================================
613// function : OrientationMatrixF
614// purpose :
615// =======================================================================
616const Graphic3d_Mat4& Graphic3d_Camera::OrientationMatrixF() const
617{
618 return *UpdateOrientation (myMatricesF).Orientation;
619}
620
621// =======================================================================
622// function : ProjectionMatrix
623// purpose :
624// =======================================================================
625const Graphic3d_Mat4d& Graphic3d_Camera::ProjectionMatrix() const
626{
627 return *UpdateProjection (myMatricesD).MProjection;
628}
629
630// =======================================================================
631// function : ProjectionMatrixF
632// purpose :
633// =======================================================================
634const Graphic3d_Mat4& Graphic3d_Camera::ProjectionMatrixF() const
635{
636 return *UpdateProjection (myMatricesF).MProjection;
637}
638
639// =======================================================================
640// function : ProjectionStereoLeft
641// purpose :
642// =======================================================================
643const Graphic3d_Mat4d& Graphic3d_Camera::ProjectionStereoLeft() const
644{
645 return *UpdateProjection (myMatricesD).LProjection;
646}
647
648// =======================================================================
649// function : ProjectionStereoLeftF
650// purpose :
651// =======================================================================
652const Graphic3d_Mat4& Graphic3d_Camera::ProjectionStereoLeftF() const
653{
654 return *UpdateProjection (myMatricesF).LProjection;
655}
656
657// =======================================================================
658// function : ProjectionStereoRight
659// purpose :
660// =======================================================================
661const Graphic3d_Mat4d& Graphic3d_Camera::ProjectionStereoRight() const
662{
663 return *UpdateProjection (myMatricesD).RProjection;
664}
665
666// =======================================================================
667// function : ProjectionStereoRightF
668// purpose :
669// =======================================================================
670const Graphic3d_Mat4& Graphic3d_Camera::ProjectionStereoRightF() const
671{
672 return *UpdateProjection (myMatricesF).RProjection;
b5ac8292 673}
674
675// =======================================================================
676// function : UpdateProjection
677// purpose :
678// =======================================================================
197ac94e 679template <typename Elem_t>
680Graphic3d_Camera::TransformMatrices<Elem_t>&
681 Graphic3d_Camera::UpdateProjection (TransformMatrices<Elem_t>& theMatrices) const
b5ac8292 682{
197ac94e 683 if (theMatrices.IsProjectionValid())
b5ac8292 684 {
197ac94e 685 return theMatrices; // for inline accessors
b5ac8292 686 }
687
197ac94e 688 theMatrices.InitProjection();
b5ac8292 689
690 // sets top of frustum based on FOVy and near clipping plane
197ac94e 691 Elem_t aScale = static_cast<Elem_t> (myScale);
692 Elem_t aZNear = static_cast<Elem_t> (myZNear);
693 Elem_t aZFar = static_cast<Elem_t> (myZFar);
694 Elem_t anAspect = static_cast<Elem_t> (myAspect);
695 Elem_t aDYHalf = 0.0;
b5ac8292 696 if (IsOrthographic())
697 {
197ac94e 698 aDYHalf = aScale * Elem_t (0.5);
b5ac8292 699 }
700 else
701 {
197ac94e 702 aDYHalf = aZNear * Elem_t (Tan (DTR_HALF * myFOVy));
b5ac8292 703 }
704
705 // sets right of frustum based on aspect ratio
197ac94e 706 Elem_t aDXHalf = anAspect * aDYHalf;
707 Elem_t aLeft = -aDXHalf;
708 Elem_t aRight = aDXHalf;
709 Elem_t aBot = -aDYHalf;
710 Elem_t aTop = aDYHalf;
b5ac8292 711
197ac94e 712 Elem_t aIOD = myIODType == IODType_Relative
713 ? static_cast<Elem_t> (myIOD * Distance())
714 : static_cast<Elem_t> (myIOD);
b5ac8292 715
197ac94e 716 Elem_t aFocus = myZFocusType == FocusType_Relative
717 ? static_cast<Elem_t> (myZFocus * Distance())
718 : static_cast<Elem_t> (myZFocus);
b5ac8292 719
720 switch (myProjType)
721 {
722 case Projection_Orthographic :
197ac94e 723 OrthoProj (aLeft, aRight, aBot, aTop, aZNear, aZFar, *theMatrices.MProjection);
b5ac8292 724 break;
725
726 case Projection_Perspective :
197ac94e 727 PerspectiveProj (aLeft, aRight, aBot, aTop, aZNear, aZFar, *theMatrices.MProjection);
b5ac8292 728 break;
729
730 case Projection_MonoLeftEye :
731 {
197ac94e 732 StereoEyeProj (aLeft, aRight, aBot, aTop,
733 aZNear, aZFar, aIOD, aFocus,
734 Standard_True, *theMatrices.MProjection);
b5ac8292 735 break;
736 }
737
738 case Projection_MonoRightEye :
739 {
197ac94e 740 StereoEyeProj (aLeft, aRight, aBot, aTop,
741 aZNear, aZFar, aIOD, aFocus,
742 Standard_False, *theMatrices.MProjection);
b5ac8292 743 break;
744 }
745
746 case Projection_Stereo :
747 {
197ac94e 748 PerspectiveProj (aLeft, aRight, aBot, aTop, aZNear, aZFar, *theMatrices.MProjection);
b5ac8292 749
197ac94e 750 StereoEyeProj (aLeft, aRight, aBot, aTop,
751 aZNear, aZFar, aIOD, aFocus,
752 Standard_True,
753 *theMatrices.LProjection);
b5ac8292 754
197ac94e 755 StereoEyeProj (aLeft, aRight, aBot, aTop,
756 aZNear, aZFar, aIOD, aFocus,
757 Standard_False,
758 *theMatrices.RProjection);
b5ac8292 759 break;
760 }
761 }
197ac94e 762
763 return theMatrices; // for inline accessors
b5ac8292 764}
765
766// =======================================================================
767// function : UpdateOrientation
768// purpose :
769// =======================================================================
197ac94e 770template <typename Elem_t>
771Graphic3d_Camera::TransformMatrices<Elem_t>&
772 Graphic3d_Camera::UpdateOrientation (TransformMatrices<Elem_t>& theMatrices) const
b5ac8292 773{
197ac94e 774 if (theMatrices.IsOrientationValid())
b5ac8292 775 {
197ac94e 776 return theMatrices; // for inline accessors
b5ac8292 777 }
778
197ac94e 779 theMatrices.InitOrientation();
780
781 NCollection_Vec3<Elem_t> anEye (static_cast<Elem_t> (myEye.X()),
782 static_cast<Elem_t> (myEye.Y()),
783 static_cast<Elem_t> (myEye.Z()));
784
785 NCollection_Vec3<Elem_t> aCenter (static_cast<Elem_t> (myCenter.X()),
786 static_cast<Elem_t> (myCenter.Y()),
787 static_cast<Elem_t> (myCenter.Z()));
b5ac8292 788
197ac94e 789 NCollection_Vec3<Elem_t> anUp (static_cast<Elem_t> (myUp.X()),
790 static_cast<Elem_t> (myUp.Y()),
791 static_cast<Elem_t> (myUp.Z()));
b5ac8292 792
197ac94e 793 NCollection_Vec3<Elem_t> anAxialScale (static_cast<Elem_t> (myAxialScale.X()),
794 static_cast<Elem_t> (myAxialScale.Y()),
795 static_cast<Elem_t> (myAxialScale.Z()));
b5ac8292 796
197ac94e 797 LookOrientation (anEye, aCenter, anUp, anAxialScale, *theMatrices.Orientation);
b5ac8292 798
197ac94e 799 return theMatrices; // for inline accessors
800}
b5ac8292 801
197ac94e 802// =======================================================================
803// function : InvalidateProjection
804// purpose :
805// =======================================================================
806void Graphic3d_Camera::InvalidateProjection()
807{
808 myMatricesD.ResetProjection();
809 myMatricesF.ResetProjection();
810 myProjectionState = (Standard_Size)Standard_Atomic_Increment (&THE_STATE_COUNTER);
811}
b5ac8292 812
197ac94e 813// =======================================================================
814// function : InvalidateOrientation
815// purpose :
816// =======================================================================
817void Graphic3d_Camera::InvalidateOrientation()
818{
819 myMatricesD.ResetOrientation();
820 myMatricesF.ResetOrientation();
821 myOrientationState = (Standard_Size)Standard_Atomic_Increment (&THE_STATE_COUNTER);
b5ac8292 822}
823
824// =======================================================================
825// function : OrthoProj
826// purpose :
827// =======================================================================
197ac94e 828template <typename Elem_t>
829void Graphic3d_Camera::OrthoProj (const Elem_t theLeft,
830 const Elem_t theRight,
831 const Elem_t theBottom,
832 const Elem_t theTop,
833 const Elem_t theNear,
834 const Elem_t theFar,
835 NCollection_Mat4<Elem_t>& theOutMx)
b5ac8292 836{
837 // row 0
197ac94e 838 theOutMx.ChangeValue (0, 0) = Elem_t (2.0) / (theRight - theLeft);
839 theOutMx.ChangeValue (0, 1) = Elem_t (0.0);
840 theOutMx.ChangeValue (0, 2) = Elem_t (0.0);
b5ac8292 841 theOutMx.ChangeValue (0, 3) = - (theRight + theLeft) / (theRight - theLeft);
842
843 // row 1
197ac94e 844 theOutMx.ChangeValue (1, 0) = Elem_t (0.0);
845 theOutMx.ChangeValue (1, 1) = Elem_t (2.0) / (theTop - theBottom);
846 theOutMx.ChangeValue (1, 2) = Elem_t (0.0);
b5ac8292 847 theOutMx.ChangeValue (1, 3) = - (theTop + theBottom) / (theTop - theBottom);
848
849 // row 2
197ac94e 850 theOutMx.ChangeValue (2, 0) = Elem_t (0.0);
851 theOutMx.ChangeValue (2, 1) = Elem_t (0.0);
852 theOutMx.ChangeValue (2, 2) = Elem_t (-2.0) / (theFar - theNear);
b5ac8292 853 theOutMx.ChangeValue (2, 3) = - (theFar + theNear) / (theFar - theNear);
854
855 // row 3
197ac94e 856 theOutMx.ChangeValue (3, 0) = Elem_t (0.0);
857 theOutMx.ChangeValue (3, 1) = Elem_t (0.0);
858 theOutMx.ChangeValue (3, 2) = Elem_t (0.0);
859 theOutMx.ChangeValue (3, 3) = Elem_t (1.0);
b5ac8292 860}
861
862// =======================================================================
863// function : PerspectiveProj
864// purpose :
865// =======================================================================
197ac94e 866template <typename Elem_t>
867void Graphic3d_Camera::PerspectiveProj (const Elem_t theLeft,
868 const Elem_t theRight,
869 const Elem_t theBottom,
870 const Elem_t theTop,
871 const Elem_t theNear,
872 const Elem_t theFar,
873 NCollection_Mat4<Elem_t>& theOutMx)
b5ac8292 874{
875 // column 0
197ac94e 876 theOutMx.ChangeValue (0, 0) = (Elem_t (2.0) * theNear) / (theRight - theLeft);
877 theOutMx.ChangeValue (1, 0) = Elem_t (0.0);
878 theOutMx.ChangeValue (2, 0) = Elem_t (0.0);
879 theOutMx.ChangeValue (3, 0) = Elem_t (0.0);
b5ac8292 880
881 // column 1
197ac94e 882 theOutMx.ChangeValue (0, 1) = Elem_t (0.0);
883 theOutMx.ChangeValue (1, 1) = (Elem_t (2.0) * theNear) / (theTop - theBottom);
884 theOutMx.ChangeValue (2, 1) = Elem_t (0.0);
885 theOutMx.ChangeValue (3, 1) = Elem_t (0.0);
b5ac8292 886
887 // column 2
888 theOutMx.ChangeValue (0, 2) = (theRight + theLeft) / (theRight - theLeft);
889 theOutMx.ChangeValue (1, 2) = (theTop + theBottom) / (theTop - theBottom);
890 theOutMx.ChangeValue (2, 2) = -(theFar + theNear) / (theFar - theNear);
197ac94e 891 theOutMx.ChangeValue (3, 2) = Elem_t (-1.0);
b5ac8292 892
893 // column 3
197ac94e 894 theOutMx.ChangeValue (0, 3) = Elem_t (0.0);
895 theOutMx.ChangeValue (1, 3) = Elem_t (0.0);
896 theOutMx.ChangeValue (2, 3) = -(Elem_t (2.0) * theFar * theNear) / (theFar - theNear);
897 theOutMx.ChangeValue (3, 3) = Elem_t (0.0);
b5ac8292 898}
899
900// =======================================================================
901// function : StereoEyeProj
902// purpose :
903// =======================================================================
197ac94e 904template <typename Elem_t>
905void Graphic3d_Camera::StereoEyeProj (const Elem_t theLeft,
906 const Elem_t theRight,
907 const Elem_t theBottom,
908 const Elem_t theTop,
909 const Elem_t theNear,
910 const Elem_t theFar,
911 const Elem_t theIOD,
912 const Elem_t theZFocus,
913 const Standard_Boolean theIsLeft,
914 NCollection_Mat4<Elem_t>& theOutMx)
b5ac8292 915{
197ac94e 916 Elem_t aDx = theIsLeft ? Elem_t (0.5) * theIOD : Elem_t (-0.5) * theIOD;
917 Elem_t aDXStereoShift = aDx * theNear / theZFocus;
b5ac8292 918
919 // construct eye projection matrix
920 PerspectiveProj (theLeft + aDXStereoShift,
921 theRight + aDXStereoShift,
922 theBottom, theTop, theNear, theFar,
b5ac8292 923 theOutMx);
924
197ac94e 925 if (theIOD != Elem_t (0.0))
b5ac8292 926 {
927 // X translation to cancel parallax
197ac94e 928 theOutMx.Translate (NCollection_Vec3<Elem_t> (aDx, Elem_t (0.0), Elem_t (0.0)));
b5ac8292 929 }
930}
931
932// =======================================================================
933// function : LookOrientation
934// purpose :
935// =======================================================================
197ac94e 936template <typename Elem_t>
937void Graphic3d_Camera::LookOrientation (const NCollection_Vec3<Elem_t>& theEye,
938 const NCollection_Vec3<Elem_t>& theLookAt,
939 const NCollection_Vec3<Elem_t>& theUpDir,
940 const NCollection_Vec3<Elem_t>& theAxialScale,
941 NCollection_Mat4<Elem_t>& theOutMx)
b5ac8292 942{
197ac94e 943 NCollection_Vec3<Elem_t> aForward = theLookAt - theEye;
b5ac8292 944 aForward.Normalize();
945
946 // side = forward x up
197ac94e 947 NCollection_Vec3<Elem_t> aSide = NCollection_Vec3<Elem_t>::Cross (aForward, theUpDir);
b5ac8292 948 aSide.Normalize();
949
950 // recompute up as: up = side x forward
197ac94e 951 NCollection_Vec3<Elem_t> anUp = NCollection_Vec3<Elem_t>::Cross (aSide, aForward);
b5ac8292 952
197ac94e 953 NCollection_Mat4<Elem_t> aLookMx;
b5ac8292 954 aLookMx.SetRow (0, aSide);
955 aLookMx.SetRow (1, anUp);
956 aLookMx.SetRow (2, -aForward);
957
197ac94e 958 theOutMx.InitIdentity();
959 theOutMx.Multiply (aLookMx);
b5ac8292 960 theOutMx.Translate (-theEye);
961
197ac94e 962 NCollection_Mat4<Elem_t> anAxialScaleMx;
b5ac8292 963 anAxialScaleMx.ChangeValue (0, 0) = theAxialScale.x();
964 anAxialScaleMx.ChangeValue (1, 1) = theAxialScale.y();
965 anAxialScaleMx.ChangeValue (2, 2) = theAxialScale.z();
966
967 theOutMx.Multiply (anAxialScaleMx);
968}