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