0024001: Stereographic rendering support
[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//
7// This library is free software; you can redistribute it and / or modify it
8// under the terms of the GNU Lesser General Public version 2.1 as published
9// by the Free Software Foundation, with special exception defined in the file
10// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11// distribution for complete text of the license and disclaimer of any warranty.
12//
13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
15
16#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>
23
24IMPLEMENT_STANDARD_HANDLE(Graphic3d_Camera, Standard_Transient)
25IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_Camera, Standard_Transient)
26
27namespace
28{
29 // (degrees -> radians) * 0.5
30 static const Standard_ShortReal DTR_HALF = 0.5f * 0.0174532925f;
31
32 // atomic state counter
33 static volatile Standard_Integer THE_STATE_COUNTER = 0;
34};
35
36// =======================================================================
37// function : Graphic3d_Camera
38// purpose :
39// =======================================================================
40Graphic3d_Camera::Graphic3d_Camera()
41: myUp (0.0, 1.0, 0.0),
42 myEye (0.0, 0.0, -1500.0),
43 myCenter (0.0, 0.0, 0.0),
44 myProjectionShift (0.0, 0.0, 0.0),
45 myAxialScale (1.0, 1.0, 1.0),
46 myProjType (Projection_Orthographic),
47 myFOVy (45.0),
48 myZNear (0.001),
49 myZFar (3000.0),
50 myAspect (1.0),
51 myScale (1000.0),
52 myZFocus (1.0),
53 myZFocusType (FocusType_Relative),
54 myIOD (0.05),
55 myIODType (IODType_Relative),
56 myNbUpdateLocks (0)
57{
58 myProjectionState = (Standard_Size)Standard_Atomic_Increment (&THE_STATE_COUNTER);
59 myOrientationState = (Standard_Size)Standard_Atomic_Increment (&THE_STATE_COUNTER);
60
61 myOrientation.InitIdentity();
62 myMProjection.InitIdentity();
63 myLProjection.InitIdentity();
64 myRProjection.InitIdentity();
65
66 UpdateProjection();
67 UpdateOrientation();
68}
69
70// =======================================================================
71// function : Graphic3d_Camera
72// purpose :
73// =======================================================================
74Graphic3d_Camera::Graphic3d_Camera (const Handle(Graphic3d_Camera)& theOther)
75: myNbUpdateLocks (0)
76{
77 Copy (theOther);
78}
79
80// =======================================================================
81// function : CopyMappingData
82// purpose :
83// =======================================================================
84void Graphic3d_Camera::CopyMappingData (const Handle(Graphic3d_Camera)& theOtherCamera)
85{
86 myProjectionShift = theOtherCamera->myProjectionShift;
87 myFOVy = theOtherCamera->myFOVy;
88 myZNear = theOtherCamera->myZNear;
89 myZFar = theOtherCamera->myZFar;
90 myAspect = theOtherCamera->myAspect;
91 myScale = theOtherCamera->myScale;
92 myZFocus = theOtherCamera->myZFocus;
93 myZFocusType = theOtherCamera->myZFocusType;
94 myIOD = theOtherCamera->myIOD;
95 myIODType = theOtherCamera->myIODType;
96 myProjType = theOtherCamera->myProjType;
97
98 myProjectionState = theOtherCamera->myProjectionState;
99
100 UpdateProjection();
101}
102
103// =======================================================================
104// function : CopyOrientationData
105// purpose :
106// =======================================================================
107void Graphic3d_Camera::CopyOrientationData (const Handle(Graphic3d_Camera)& theOtherCamera)
108{
109 myUp = theOtherCamera->myUp;
110 myEye = theOtherCamera->myEye;
111 myCenter = theOtherCamera->myCenter;
112 myAxialScale = theOtherCamera->myAxialScale;
113
114 myOrientationState = theOtherCamera->myOrientationState;
115
116 UpdateOrientation();
117}
118
119// =======================================================================
120// function : Copy
121// purpose :
122// =======================================================================
123void Graphic3d_Camera::Copy (const Handle(Graphic3d_Camera)& theOther)
124{
125 BeginUpdate();
126 CopyMappingData (theOther);
127 CopyOrientationData (theOther);
128 EndUpdate();
129}
130
131// =======================================================================
132// function : SetEye
133// purpose :
134// =======================================================================
135void Graphic3d_Camera::SetEye (const gp_Pnt& theEye)
136{
137 myEye = theEye;
138 UpdateOrientation();
139}
140
141// =======================================================================
142// function : SetCenter
143// purpose :
144// =======================================================================
145void Graphic3d_Camera::SetCenter (const gp_Pnt& theCenter)
146{
147 myCenter = theCenter;
148 UpdateOrientation();
149}
150
151// =======================================================================
152// function : SetUp
153// purpose :
154// =======================================================================
155void Graphic3d_Camera::SetUp (const gp_Dir& theUp)
156{
157 myUp = theUp;
158 UpdateOrientation();
159}
160
161// =======================================================================
162// function : SetProjectionShift
163// purpose :
164// =======================================================================
165void Graphic3d_Camera::SetProjectionShift (const gp_Pnt& theProjShift)
166{
167 myProjectionShift = theProjShift;
168 UpdateProjection();
169}
170
171// =======================================================================
172// function : SetAxialScale
173// purpose :
174// =======================================================================
175void Graphic3d_Camera::SetAxialScale (const gp_Pnt& theAxialScale)
176{
177 myAxialScale = theAxialScale;
178 UpdateOrientation();
179}
180
181// =======================================================================
182// function : SetDistance
183// purpose :
184// =======================================================================
185void Graphic3d_Camera::SetDistance (const Standard_Real theDistance)
186{
187 gp_Vec aCenter2Eye (Direction());
188 aCenter2Eye.Reverse();
189 aCenter2Eye.Scale (theDistance);
190 SetEye (Center().Translated (aCenter2Eye));
191}
192
193// =======================================================================
194// function : Distance
195// purpose :
196// =======================================================================
197Standard_Real Graphic3d_Camera::Distance() const
198{
199 return myEye.Distance (myCenter);
200}
201
202// =======================================================================
203// function : SetDirection
204// purpose :
205// =======================================================================
206void Graphic3d_Camera::SetDirection (const gp_Dir& theDir)
207{
208 gp_Vec aScaledDir (theDir);
209 aScaledDir.Scale (Distance());
210 aScaledDir.Reverse();
211 SetEye (Center().Translated (aScaledDir));
212}
213
214// =======================================================================
215// function : Direction
216// purpose :
217// =======================================================================
218gp_Dir Graphic3d_Camera::Direction() const
219{
220 return gp_Dir (gp_Vec (myEye, myCenter));
221}
222
223// =======================================================================
224// function : SetScale
225// purpose :
226// =======================================================================
227void Graphic3d_Camera::SetScale (const Standard_Real theScale)
228{
229 myScale = theScale;
230
231 switch (myProjType)
232 {
233 case Projection_Perspective :
234 case Projection_Stereo :
235 case Projection_MonoLeftEye :
236 case Projection_MonoRightEye :
237 {
238 Standard_Real aDistance = theScale * 0.5 / Tan(myFOVy * M_PI / 360.0);
239 SetDistance (aDistance);
240 }
241
242 default :
243 break;
244 }
245
246 UpdateProjection();
247}
248
249// =======================================================================
250// function : Scale
251// purpose :
252// =======================================================================
253Standard_Real Graphic3d_Camera::Scale() const
254{
255 switch (myProjType)
256 {
257 case Projection_Orthographic :
258 return myScale;
259
260 // case Projection_Perspective :
261 // case Projection_Stereo :
262 // case Projection_MonoLeftEye :
263 // case Projection_MonoRightEye :
264 default :
265 return Distance() * 2.0 * Tan(myFOVy * M_PI / 360.0);
266 }
267}
268
269// =======================================================================
270// function : SetProjectionType
271// purpose :
272// =======================================================================
273void Graphic3d_Camera::SetProjectionType (const Projection theProjectionType)
274{
275 Projection anOldType = myProjType;
276
277 if (anOldType == theProjectionType)
278 {
279 return;
280 }
281
282 myProjType = theProjectionType;
283
284 switch (myProjType)
285 {
286 case Projection_Orthographic :
287 case Projection_Perspective :
288 case Projection_MonoLeftEye :
289 case Projection_MonoRightEye :
290 myLProjection.InitIdentity();
291 myRProjection.InitIdentity();
292 break;
293
294 default:
295 break;
296 }
297
298 UpdateProjection();
299}
300
301// =======================================================================
302// function : SetFOVy
303// purpose :
304// =======================================================================
305void Graphic3d_Camera::SetFOVy (const Standard_Real theFOVy)
306{
307 myFOVy = theFOVy;
308 UpdateProjection();
309}
310
311// =======================================================================
312// function : SetZNear
313// purpose :
314// =======================================================================
315void Graphic3d_Camera::SetZNear (const Standard_Real theZNear)
316{
317 myZNear = theZNear;
318
319 // it is important to prevent too low ZNear values relatively to ZFar
320 // so we can not just pass Precision::Confusion() to it
321 const Standard_Real aTolerance = 0.001;
322 const Standard_Real aMinimumZ = myZFar * aTolerance;
323 const Standard_Real aMinimumGap = aTolerance;
324 // while it is possible to manually set up pretty small ZNear value,
325 // it may affect project / unproject operations dramatically
326 if (myZNear < aMinimumZ)
327 {
328 myZNear = aMinimumZ;
329 }
330
331 if (myZFar < (myZNear + aMinimumGap))
332 {
333 myZFar = myZNear + aMinimumGap;
334 }
335
336 UpdateProjection();
337}
338
339// =======================================================================
340// function : SetZFar
341// purpose :
342// =======================================================================
343void Graphic3d_Camera::SetZFar (const Standard_Real theZFar)
344{
345 myZFar = theZFar;
346
347 // it is important to prevent too low ZNear values relatively to ZFar
348 // so we can not just pass Precision::Confusion() to it
349 const Standard_Real aTolerance = 0.001;
350 const Standard_Real aMinimumGap = aTolerance;
351
352 // while it is possible to manually set up pretty small ZNear value,
353 // it may affect project / unproject operations dramatically
354 if (myZFar < (myZNear + aMinimumGap))
355 {
356 myZFar = myZNear + aMinimumGap;
357 }
358
359 UpdateProjection();
360}
361
362// =======================================================================
363// function : SetAspect
364// purpose :
365// =======================================================================
366void Graphic3d_Camera::SetAspect (const Standard_Real theAspect)
367{
368 myAspect = theAspect;
369 UpdateProjection();
370}
371
372// =======================================================================
373// function : SetZFocus
374// purpose :
375// =======================================================================
376void Graphic3d_Camera::SetZFocus(const FocusType theType, const Standard_Real theZFocus)
377{
378 myZFocusType = theType;
379 myZFocus = theZFocus;
380 UpdateProjection();
381}
382
383// =======================================================================
384// function : SetIOD
385// purpose :
386// =======================================================================
387void Graphic3d_Camera::SetIOD (const IODType theType, const Standard_Real theIOD)
388{
389 myIODType = theType;
390 myIOD = theIOD;
391 UpdateProjection();
392}
393
394// =======================================================================
395// function : OrthogonalizeUp
396// purpose :
397// =======================================================================
398void Graphic3d_Camera::OrthogonalizeUp()
399{
400 gp_Dir aDir = Direction();
401 gp_Dir aLeft = aDir.Crossed (Up());
402
403 // recompute up as: up = left x direction
404 SetUp (aLeft.Crossed (aDir));
405}
406
407// =======================================================================
408// function : BeginUpdate
409// purpose :
410// =======================================================================
411void Graphic3d_Camera::BeginUpdate()
412{
413 myNbUpdateLocks++;
414}
415
416// =======================================================================
417// function : EndUpdate
418// purpose :
419// =======================================================================
420void Graphic3d_Camera::EndUpdate()
421{
422 if (myNbUpdateLocks > 0)
423 myNbUpdateLocks--;
424
425 // if number of locks > 0, the updates are bypassed
426 UpdateProjection();
427 UpdateOrientation();
428}
429
430// =======================================================================
431// function : Transform
432// purpose :
433// =======================================================================
434void Graphic3d_Camera::Transform (const gp_Trsf& theTrsf)
435{
436 myUp.Transform (theTrsf);
437 myEye.Transform (theTrsf);
438 myCenter.Transform (theTrsf);
439 UpdateOrientation();
440}
441
442// =======================================================================
443// function : safePointCast
444// purpose :
445// =======================================================================
446static Graphic3d_Vec4 safePointCast (const gp_Pnt& thePnt)
447{
448 Standard_Real aLim = 1e15f;
449
450 // have to deal with values greater then max float
451 gp_Pnt aSafePoint = thePnt;
452 const Standard_Real aBigFloat = aLim * 0.1f;
453 if (Abs (aSafePoint.X()) > aLim)
454 aSafePoint.SetX (aSafePoint.X() >= 0 ? aBigFloat : -aBigFloat);
455 if (Abs (aSafePoint.Y()) > aLim)
456 aSafePoint.SetY (aSafePoint.Y() >= 0 ? aBigFloat : -aBigFloat);
457 if (Abs (aSafePoint.Z()) > aLim)
458 aSafePoint.SetZ (aSafePoint.Z() >= 0 ? aBigFloat : -aBigFloat);
459
460 // convert point
461 Graphic3d_Vec4 aPnt (static_cast<Standard_ShortReal> (aSafePoint.X()),
462 static_cast<Standard_ShortReal> (aSafePoint.Y()),
463 static_cast<Standard_ShortReal> (aSafePoint.Z()), 1.0f);
464
465 return aPnt;
466}
467
468// =======================================================================
469// function : Project
470// purpose :
471// =======================================================================
472gp_Pnt Graphic3d_Camera::Project (const gp_Pnt& thePnt) const
473{
474 const Graphic3d_Mat4& aViewMx = OrientationMatrix();
475 const Graphic3d_Mat4& aProjMx = ProjectionMatrix();
476
477 // use compatible type of point
478 Graphic3d_Vec4 aPnt = safePointCast (thePnt);
479
480 aPnt = aViewMx * aPnt; // convert to view coordinate space
481 aPnt = aProjMx * aPnt; // convert to projection coordinate space
482
483 const Standard_Real aInvW = 1.0 / Standard_Real (aPnt.w());
484
485 return gp_Pnt (aPnt.x() * aInvW, aPnt.y() * aInvW, aPnt.z() * aInvW);
486}
487
488// =======================================================================
489// function : UnProject
490// purpose :
491// =======================================================================
492gp_Pnt Graphic3d_Camera::UnProject (const gp_Pnt& thePnt) const
493{
494 const Graphic3d_Mat4& aViewMx = OrientationMatrix();
495 const Graphic3d_Mat4& aProjMx = ProjectionMatrix();
496
497 Graphic3d_Mat4 aInvView;
498 Graphic3d_Mat4 aInvProj;
499
500 // this case should never happen
501 if (!aViewMx.Inverted (aInvView) || !aProjMx.Inverted (aInvProj))
502 {
503 return gp_Pnt (0.0, 0.0, 0.0);
504 }
505
506 // use compatible type of point
507 Graphic3d_Vec4 aPnt = safePointCast (thePnt);
508
509 aPnt = aInvProj * aPnt; // convert to view coordinate space
510 aPnt = aInvView * aPnt; // convert to world coordinate space
511
512 const Standard_Real aInvW = 1.0 / Standard_Real (aPnt.w());
513
514 return gp_Pnt (aPnt.x() * aInvW, aPnt.y() * aInvW, aPnt.z() * aInvW);
515}
516
517// =======================================================================
518// function : ConvertView2Proj
519// purpose :
520// =======================================================================
521gp_Pnt Graphic3d_Camera::ConvertView2Proj (const gp_Pnt& thePnt) const
522{
523 const Graphic3d_Mat4& aProjMx = ProjectionMatrix();
524
525 // use compatible type of point
526 Graphic3d_Vec4 aPnt = safePointCast (thePnt);
527
528 aPnt = aProjMx * aPnt; // convert to projection coordinate space
529
530 const Standard_Real aInvW = 1.0 / Standard_Real (aPnt.w());
531
532 return gp_Pnt (aPnt.x() * aInvW, aPnt.y() * aInvW, aPnt.z() * aInvW);
533}
534
535// =======================================================================
536// function : ConvertProj2View
537// purpose :
538// =======================================================================
539gp_Pnt Graphic3d_Camera::ConvertProj2View (const gp_Pnt& thePnt) const
540{
541 const Graphic3d_Mat4& aProjMx = ProjectionMatrix();
542
543 Graphic3d_Mat4 aInvProj;
544
545 // this case should never happen, but...
546 if (!aProjMx.Inverted (aInvProj))
547 {
548 return gp_Pnt(0, 0, 0);
549 }
550
551 // use compatible type of point
552 Graphic3d_Vec4 aPnt = safePointCast (thePnt);
553
554 aPnt = aInvProj * aPnt; // convert to view coordinate space
555
556 const Standard_Real aInvW = 1.0 / Standard_Real (aPnt.w());
557
558 return gp_Pnt (aPnt.x() * aInvW, aPnt.y() * aInvW, aPnt.z() * aInvW);
559}
560
561// =======================================================================
562// function : ConvertWorld2View
563// purpose :
564// =======================================================================
565gp_Pnt Graphic3d_Camera::ConvertWorld2View (const gp_Pnt& thePnt) const
566{
567 const Graphic3d_Mat4& aViewMx = OrientationMatrix();
568
569 // use compatible type of point
570 Graphic3d_Vec4 aPnt = safePointCast (thePnt);
571
572 aPnt = aViewMx * aPnt; // convert to view coordinate space
573
574 const Standard_Real aInvW = 1.0 / Standard_Real (aPnt.w());
575
576 return gp_Pnt (aPnt.x() * aInvW, aPnt.y() * aInvW, aPnt.z() * aInvW);
577}
578
579// =======================================================================
580// function : ConvertView2World
581// purpose :
582// =======================================================================
583gp_Pnt Graphic3d_Camera::ConvertView2World (const gp_Pnt& thePnt) const
584{
585 const Graphic3d_Mat4& aViewMx = OrientationMatrix();
586
587 Graphic3d_Mat4 aInvView;
588
589 if (!aViewMx.Inverted (aInvView))
590 {
591 return gp_Pnt(0, 0, 0);
592 }
593
594 // use compatible type of point
595 Graphic3d_Vec4 aPnt = safePointCast (thePnt);
596
597 aPnt = aInvView * aPnt; // convert to world coordinate space
598
599 const Standard_Real aInvW = 1.0 / Standard_Real (aPnt.w());
600
601 return gp_Pnt (aPnt.x() * aInvW, aPnt.y() * aInvW, aPnt.z() * aInvW);
602}
603
604// =======================================================================
605// function : ViewDimensions
606// purpose :
607// =======================================================================
608gp_Pnt Graphic3d_Camera::ViewDimensions () const
609{
610 // view plane dimensions
611 Standard_Real aSizeY = IsOrthographic() ? myScale : (2.0 * Distance() * Tan (DTR_HALF * myFOVy));
612 Standard_Real aSizeX = myAspect * aSizeY;
613
614 // and frustum depth
615 return gp_Pnt (aSizeX, aSizeY, myZFar - myZNear);
616}
617
618// =======================================================================
619// function : WindowLimit
620// purpose :
621// =======================================================================
622void Graphic3d_Camera::WindowLimit (Standard_Real& theUMin,
623 Standard_Real& theVMin,
624 Standard_Real& theUMax,
625 Standard_Real& theVMax) const
626{
627 gp_Pnt aViewDims = ViewDimensions();
628 gp_Pnt aShift = ProjectionShift();
629 theUMin = -aViewDims.X() * 0.5 - aShift.X();
630 theVMin = -aViewDims.Y() * 0.5 - aShift.Y();
631 theUMax = aViewDims.X() * 0.5 - aShift.X();
632 theVMax = aViewDims.Y() * 0.5 - aShift.Y();
633}
634
635// =======================================================================
636// function : UpdateProjection
637// purpose :
638// =======================================================================
639void Graphic3d_Camera::UpdateProjection()
640{
641 if (myNbUpdateLocks > 0)
642 {
643 return;
644 }
645
646 myProjectionState = (Standard_Size)Standard_Atomic_Increment (&THE_STATE_COUNTER);
647
648 // sets top of frustum based on FOVy and near clipping plane
649 Standard_Real aDYHalf;
650 if (IsOrthographic())
651 {
652 aDYHalf = myScale * 0.5;
653 }
654 else
655 {
656 aDYHalf = myZNear * Tan (DTR_HALF * myFOVy);
657 }
658
659 // sets right of frustum based on aspect ratio
660 Standard_Real aDXHalf = myAspect * aDYHalf;
661
662 Standard_ShortReal aLeft = (Standard_ShortReal) -aDXHalf;
663 Standard_ShortReal aRight = (Standard_ShortReal) aDXHalf;
664 Standard_ShortReal aBot = (Standard_ShortReal) -aDYHalf;
665 Standard_ShortReal aTop = (Standard_ShortReal) aDYHalf;
666 Standard_ShortReal aNear = (Standard_ShortReal) myZNear;
667 Standard_ShortReal aFar = (Standard_ShortReal) myZFar;
668 Standard_ShortReal aShiftX = (Standard_ShortReal) myProjectionShift.X();
669 Standard_ShortReal aShiftY = (Standard_ShortReal) myProjectionShift.Y();
670
671 Standard_ShortReal aIOD = (myIODType == IODType_Relative)
672 ? (Standard_ShortReal)(myIOD * Distance())
673 : (Standard_ShortReal)(myIOD);
674
675 Standard_ShortReal aFocus = (myZFocusType == FocusType_Relative)
676 ? (Standard_ShortReal)(myZFocus * Distance())
677 : (Standard_ShortReal)(myZFocus);
678
679 switch (myProjType)
680 {
681 case Projection_Orthographic :
682 OrthoProj (aLeft, aRight, aBot, aTop, aNear, aFar, aShiftX, aShiftY, myMProjection);
683 break;
684
685 case Projection_Perspective :
686 PerspectiveProj (aLeft, aRight, aBot, aTop, aNear, aFar, aShiftX, aShiftY, myMProjection);
687 break;
688
689 case Projection_MonoLeftEye :
690 {
691 StereoEyeProj (aLeft, aRight, aBot, aTop, aNear,
692 aFar, aIOD, aFocus, aShiftX, aShiftY,
693 Standard_True, myMProjection);
694 break;
695 }
696
697 case Projection_MonoRightEye :
698 {
699 StereoEyeProj (aLeft, aRight, aBot, aTop, aNear,
700 aFar, aIOD, aFocus, aShiftX, aShiftY,
701 Standard_False, myMProjection);
702 break;
703 }
704
705 case Projection_Stereo :
706 {
707 PerspectiveProj (aLeft, aRight, aBot, aTop, aNear, aFar, aShiftX, aShiftY, myMProjection);
708
709 StereoEyeProj (aLeft, aRight, aBot, aTop, aNear,
710 aFar, aIOD, aFocus, aShiftX, aShiftY,
711 Standard_True, myLProjection);
712
713 StereoEyeProj (aLeft, aRight, aBot, aTop, aNear,
714 aFar, aIOD, aFocus, aShiftX, aShiftY,
715 Standard_False, myRProjection);
716 break;
717 }
718 }
719}
720
721// =======================================================================
722// function : UpdateOrientation
723// purpose :
724// =======================================================================
725void Graphic3d_Camera::UpdateOrientation()
726{
727 if (myNbUpdateLocks > 0)
728 {
729 return;
730 }
731
732 myOrientationState = (Standard_Size)Standard_Atomic_Increment (&THE_STATE_COUNTER);
733
734 Graphic3d_Vec3 anEye ((Standard_ShortReal) myEye.X(),
735 (Standard_ShortReal) myEye.Y(),
736 (Standard_ShortReal) myEye.Z());
737
738 Graphic3d_Vec3 aCenter ((Standard_ShortReal) myCenter.X(),
739 (Standard_ShortReal) myCenter.Y(),
740 (Standard_ShortReal) myCenter.Z());
741
742 Graphic3d_Vec3 anUp ((Standard_ShortReal) myUp.X(),
743 (Standard_ShortReal) myUp.Y(),
744 (Standard_ShortReal) myUp.Z());
745
746 Graphic3d_Vec3 anAxialScale ((Standard_ShortReal) myAxialScale.X(),
747 (Standard_ShortReal) myAxialScale.Y(),
748 (Standard_ShortReal) myAxialScale.Z());
749
750 LookOrientation (anEye, aCenter, anUp, anAxialScale, myOrientation);
751
752 // Update orthogonalized Up vector
753 myUp = gp_Dir (anUp.x(), anUp.y(), anUp.z());
754}
755
756// =======================================================================
757// function : OrthoProj
758// purpose :
759// =======================================================================
760void Graphic3d_Camera::OrthoProj (const Standard_ShortReal theLeft,
761 const Standard_ShortReal theRight,
762 const Standard_ShortReal theBottom,
763 const Standard_ShortReal theTop,
764 const Standard_ShortReal theNear,
765 const Standard_ShortReal theFar,
766 const Standard_ShortReal theShiftX,
767 const Standard_ShortReal theShiftY,
768 Graphic3d_Mat4& theOutMx)
769{
770 // row 0
771 theOutMx.ChangeValue (0, 0) = 2.0f / (theRight - theLeft);
772 theOutMx.ChangeValue (0, 1) = 0.0f;
773 theOutMx.ChangeValue (0, 2) = 0.0f;
774 theOutMx.ChangeValue (0, 3) = - (theRight + theLeft) / (theRight - theLeft);
775
776 // row 1
777 theOutMx.ChangeValue (1, 0) = 0.0f;
778 theOutMx.ChangeValue (1, 1) = 2.0f / (theTop - theBottom);
779 theOutMx.ChangeValue (1, 2) = 0.0f;
780 theOutMx.ChangeValue (1, 3) = - (theTop + theBottom) / (theTop - theBottom);
781
782 // row 2
783 theOutMx.ChangeValue (2, 0) = 0.0f;
784 theOutMx.ChangeValue (2, 1) = 0.0f;
785 theOutMx.ChangeValue (2, 2) = -2.0f / (theFar - theNear);
786 theOutMx.ChangeValue (2, 3) = - (theFar + theNear) / (theFar - theNear);
787
788 // row 3
789 theOutMx.ChangeValue (3, 0) = 0.0f;
790 theOutMx.ChangeValue (3, 1) = 0.0f;
791 theOutMx.ChangeValue (3, 2) = 0.0f;
792 theOutMx.ChangeValue (3, 3) = 1.0f;
793
794 Graphic3d_Mat4 aViewportShift;
795 aViewportShift.ChangeValue (0, 3) = theShiftX;
796 aViewportShift.ChangeValue (1, 3) = theShiftY;
797
798 theOutMx.Multiply (aViewportShift);
799}
800
801// =======================================================================
802// function : PerspectiveProj
803// purpose :
804// =======================================================================
805void Graphic3d_Camera::PerspectiveProj (const Standard_ShortReal theLeft,
806 const Standard_ShortReal theRight,
807 const Standard_ShortReal theBottom,
808 const Standard_ShortReal theTop,
809 const Standard_ShortReal theNear,
810 const Standard_ShortReal theFar,
811 const Standard_ShortReal theShiftX,
812 const Standard_ShortReal theShiftY,
813 Graphic3d_Mat4& theOutMx)
814{
815 // column 0
816 theOutMx.ChangeValue (0, 0) = (2.0f * theNear) / (theRight - theLeft);
817 theOutMx.ChangeValue (1, 0) = 0.0f;
818 theOutMx.ChangeValue (2, 0) = 0.0f;
819 theOutMx.ChangeValue (3, 0) = 0.0f;
820
821 // column 1
822 theOutMx.ChangeValue (0, 1) = 0.0f;
823 theOutMx.ChangeValue (1, 1) = (2.0f * theNear) / (theTop - theBottom);
824 theOutMx.ChangeValue (2, 1) = 0.0f;
825 theOutMx.ChangeValue (3, 1) = 0.0f;
826
827 // column 2
828 theOutMx.ChangeValue (0, 2) = (theRight + theLeft) / (theRight - theLeft);
829 theOutMx.ChangeValue (1, 2) = (theTop + theBottom) / (theTop - theBottom);
830 theOutMx.ChangeValue (2, 2) = -(theFar + theNear) / (theFar - theNear);
831 theOutMx.ChangeValue (3, 2) = -1.0f;
832
833 // column 3
834 theOutMx.ChangeValue (0, 3) = 0.0f;
835 theOutMx.ChangeValue (1, 3) = 0.0f;
836 theOutMx.ChangeValue (2, 3) = -(2.0f * theFar * theNear) / (theFar - theNear);
837 theOutMx.ChangeValue (3, 3) = 0.0f;
838
839 Graphic3d_Mat4 aViewportShift;
840 aViewportShift.ChangeValue (0, 3) = theShiftX;
841 aViewportShift.ChangeValue (1, 3) = theShiftY;
842
843 theOutMx.Multiply (aViewportShift);
844}
845
846// =======================================================================
847// function : StereoEyeProj
848// purpose :
849// =======================================================================
850void Graphic3d_Camera::StereoEyeProj (const Standard_ShortReal theLeft,
851 const Standard_ShortReal theRight,
852 const Standard_ShortReal theBottom,
853 const Standard_ShortReal theTop,
854 const Standard_ShortReal theNear,
855 const Standard_ShortReal theFar,
856 const Standard_ShortReal theIOD,
857 const Standard_ShortReal theZFocus,
858 const Standard_ShortReal theShiftX,
859 const Standard_ShortReal theShiftY,
860 const Standard_Boolean theIsLeft,
861 Graphic3d_Mat4& theOutMx)
862{
863 Standard_ShortReal aDx = theIsLeft ? ( 0.5f * theIOD) : (-0.5f * theIOD);
864 Standard_ShortReal aDXStereoShift = aDx * theNear / theZFocus;
865
866 // construct eye projection matrix
867 PerspectiveProj (theLeft + aDXStereoShift,
868 theRight + aDXStereoShift,
869 theBottom, theTop, theNear, theFar,
870 theShiftX, theShiftY,
871 theOutMx);
872
873 if (theIOD != 0.0f)
874 {
875 // X translation to cancel parallax
876 theOutMx.Translate (Graphic3d_Vec3 (aDx, 0.0f, 0.0f));
877 }
878}
879
880// =======================================================================
881// function : LookOrientation
882// purpose :
883// =======================================================================
884void Graphic3d_Camera::LookOrientation (const Graphic3d_Vec3& theEye,
885 const Graphic3d_Vec3& theLookAt,
886 Graphic3d_Vec3& theUpDir,
887 const Graphic3d_Vec3& theAxialScale,
888 Graphic3d_Mat4& theOutMx)
889{
890 Graphic3d_Vec3 aForward = theLookAt - theEye;
891 aForward.Normalize();
892
893 // side = forward x up
894 Graphic3d_Vec3 aSide = Graphic3d_Vec3::Cross (aForward, theUpDir);
895 aSide.Normalize();
896
897 // recompute up as: up = side x forward
898 Graphic3d_Vec3 anUp = Graphic3d_Vec3::Cross (aSide, aForward);
899 theUpDir = anUp;
900
901 Graphic3d_Mat4 aLookMx;
902 aLookMx.SetRow (0, aSide);
903 aLookMx.SetRow (1, anUp);
904 aLookMx.SetRow (2, -aForward);
905
906 theOutMx.InitIdentity();
907 theOutMx.Multiply (aLookMx);
908
909 theOutMx.Translate (-theEye);
910
911 Graphic3d_Mat4 anAxialScaleMx;
912 anAxialScaleMx.ChangeValue (0, 0) = theAxialScale.x();
913 anAxialScaleMx.ChangeValue (1, 1) = theAxialScale.y();
914 anAxialScaleMx.ChangeValue (2, 2) = theAxialScale.z();
915
916 theOutMx.Multiply (anAxialScaleMx);
917}