18c117fe7d7e4b6853f48134707e94cd19b61eec
[occt.git] / src / Graphic3d / Graphic3d_CView.cxx
1 // Copyright (c) 2015 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14 #include <Graphic3d_CView.hxx>
15
16 #include <Aspect_OpenVRSession.hxx>
17 #include <Graphic3d_Layer.hxx>
18 #include <Graphic3d_MapIteratorOfMapOfStructure.hxx>
19 #include <Graphic3d_StructureManager.hxx>
20
21 IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_CView,Graphic3d_DataStructureManager)
22
23 //=======================================================================
24 //function : Constructor
25 //purpose  :
26 //=======================================================================
27 Graphic3d_CView::Graphic3d_CView (const Handle(Graphic3d_StructureManager)& theMgr)
28 : myBgColor                (Quantity_NOC_BLACK),
29   myStructureManager       (theMgr),
30   myCamera                 (new Graphic3d_Camera()),
31   myHiddenObjects          (new Graphic3d_NMapOfTransient()),
32   myIsInComputedMode       (Standard_False),
33   myIsActive               (Standard_False),
34   myIsRemoved              (Standard_False),
35   myShadingModel           (Graphic3d_TOSM_FRAGMENT),
36   myVisualization          (Graphic3d_TOV_WIREFRAME),
37   myUnitFactor             (1.0)
38 {
39   myId = myStructureManager->Identification (this);
40 }
41
42 //=======================================================================
43 //function : Destructor
44 //purpose  :
45 //=======================================================================
46 Graphic3d_CView::~Graphic3d_CView()
47 {
48   myXRSession.Nullify();
49   if (!IsRemoved())
50   {
51     myStructureManager->UnIdentification (this);
52   }
53 }
54
55 // =======================================================================
56 // function : Activate
57 // purpose  :
58 // =======================================================================
59 void Graphic3d_CView::Activate()
60 {
61   if (!IsActive())
62   {
63     myIsActive = Standard_True;
64
65     // Activation of a new view =>
66     // Display structures that can be displayed in this new view.
67     // All structures with status
68     // Displayed in ViewManager are returned and displayed in
69     // the view directly, if the structure is not already
70     // displayed and if the view accepts it in its context.
71     Graphic3d_MapOfStructure aDisplayedStructs;
72     myStructureManager->DisplayedStructures (aDisplayedStructs);
73     for (Graphic3d_MapIteratorOfMapOfStructure aStructIter (aDisplayedStructs); aStructIter.More(); aStructIter.Next())
74     {
75       const Handle(Graphic3d_Structure)& aStruct = aStructIter.Key();
76       if (IsDisplayed (aStruct))
77       {
78         continue;
79       }
80
81       // If the structure can be displayed in the new context of the view, it is displayed.
82       const Graphic3d_TypeOfAnswer anAnswer = acceptDisplay (aStruct->Visual());
83       if (anAnswer == Graphic3d_TOA_YES
84        || anAnswer == Graphic3d_TOA_COMPUTE)
85       {
86         Display (aStruct);
87       }
88     }
89   }
90
91   Update();
92 }
93
94 // =======================================================================
95 // function : Deactivate
96 // purpose  :
97 // =======================================================================
98 void Graphic3d_CView::Deactivate()
99 {
100   if (IsActive())
101   {
102     // Deactivation of a view =>
103     // Removal of structures displayed in this view.
104     // All structures with status
105     // Displayed in ViewManager are returned and removed from
106     // the view directly, if the structure is not already
107     // displayed and if the view accepts it in its context.
108     Graphic3d_MapOfStructure aDisplayedStructs;
109     myStructureManager->DisplayedStructures (aDisplayedStructs);
110     for (Graphic3d_MapIteratorOfMapOfStructure aStructIter (aDisplayedStructs); aStructIter.More(); aStructIter.Next())
111     {
112       const Handle(Graphic3d_Structure)& aStruct = aStructIter.Key();
113       if (!IsDisplayed (aStruct))
114       {
115         continue;
116       }
117
118       const Graphic3d_TypeOfAnswer anAnswer = acceptDisplay (aStruct->Visual());
119       if (anAnswer == Graphic3d_TOA_YES
120        || anAnswer == Graphic3d_TOA_COMPUTE)
121       {
122         Erase (aStruct);
123       }
124     }
125
126     Update();
127     myIsActive = Standard_False;
128   }
129 }
130
131 // ========================================================================
132 // function : Remove
133 // purpose  :
134 // ========================================================================
135 void Graphic3d_CView::Remove()
136 {
137   if (IsRemoved())
138   {
139     return;
140   }
141
142   Graphic3d_MapOfStructure aDisplayedStructs (myStructsDisplayed);
143
144   for (Graphic3d_MapIteratorOfMapOfStructure aStructIter (aDisplayedStructs); aStructIter.More(); aStructIter.Next())
145   {
146     Erase (aStructIter.Value());
147   }
148
149   myStructsToCompute.Clear();
150   myStructsComputed .Clear();
151   myStructsDisplayed.Clear();
152
153   if (!myStructureManager.IsNull())
154   {
155     myStructureManager->UnIdentification (this);
156   }
157
158   myIsActive  = Standard_False;
159   myIsRemoved = Standard_True;
160 }
161
162 // ========================================================================
163 // function : SetComputedMode
164 // purpose  :
165 // ========================================================================
166 void Graphic3d_CView::SetComputedMode (const Standard_Boolean theMode)
167 {
168   if (( theMode &&  myIsInComputedMode)
169    || (!theMode && !myIsInComputedMode))
170   {
171     return;
172   }
173
174   myIsInComputedMode = theMode;
175   if (!myIsInComputedMode)
176   {
177     for (Graphic3d_MapOfStructure::Iterator aStructIter (myStructsDisplayed); aStructIter.More(); aStructIter.Next())
178     {
179       const Handle(Graphic3d_Structure)& aStruct  = aStructIter.Key();
180       const Graphic3d_TypeOfAnswer        anAnswer = acceptDisplay (aStruct->Visual());
181       if (anAnswer != Graphic3d_TOA_COMPUTE)
182       {
183         continue;
184       }
185
186       const Standard_Integer anIndex = IsComputed (aStruct);
187       if (anIndex != 0)
188       {
189         const Handle(Graphic3d_Structure)& aStructComp = myStructsComputed.Value (anIndex);
190         eraseStructure   (aStructComp->CStructure());
191         displayStructure (aStruct->CStructure(), aStruct->DisplayPriority());
192       }
193     }
194     return;
195   }
196
197   for (Graphic3d_MapOfStructure::Iterator aDispStructIter (myStructsDisplayed); aDispStructIter.More(); aDispStructIter.Next())
198   {
199     Handle(Graphic3d_Structure) aStruct  = aDispStructIter.Key();
200     const Graphic3d_TypeOfAnswer anAnswer = acceptDisplay (aStruct->Visual());
201     if (anAnswer != Graphic3d_TOA_COMPUTE)
202     {
203       continue;
204     }
205
206     const Standard_Integer anIndex = IsComputed (aStruct);
207     if (anIndex != 0)
208     {
209       eraseStructure   (aStruct->CStructure());
210       displayStructure (myStructsComputed.Value (anIndex)->CStructure(), aStruct->DisplayPriority());
211
212       Display (aStruct);
213       if (aStruct->IsHighlighted())
214       {
215         const Handle(Graphic3d_Structure)& aCompStruct = myStructsComputed.Value (anIndex);
216         if (!aCompStruct->IsHighlighted())
217         {
218           aCompStruct->Highlight (aStruct->HighlightStyle(), Standard_False);
219         }
220       }
221     }
222     else
223     {
224       Handle(Graphic3d_Structure) aCompStruct;
225       aStruct->computeHLR (myCamera, aCompStruct);
226       aCompStruct->SetHLRValidation (Standard_True);
227
228       const Standard_Boolean toComputeWireframe = myVisualization == Graphic3d_TOV_WIREFRAME
229                                                 && aStruct->ComputeVisual() != Graphic3d_TOS_SHADING;
230       const Standard_Boolean toComputeShading   = myVisualization == Graphic3d_TOV_SHADING
231                                                 && aStruct->ComputeVisual() != Graphic3d_TOS_WIREFRAME;
232       if (toComputeWireframe) aCompStruct->SetVisual (Graphic3d_TOS_WIREFRAME);
233       if (toComputeShading  ) aCompStruct->SetVisual (Graphic3d_TOS_SHADING);
234
235       if (aStruct->IsHighlighted())
236       {
237         aCompStruct->Highlight (aStruct->HighlightStyle(), Standard_False);
238       }
239
240       Standard_Boolean hasResult = Standard_False;
241       const Standard_Integer aNbToCompute = myStructsToCompute.Length();
242       const Standard_Integer aStructId    = aStruct->Identification();
243       for (Standard_Integer aToCompStructIter = 1; aToCompStructIter <= aNbToCompute; ++aToCompStructIter)
244       {
245         if (myStructsToCompute.Value (aToCompStructIter)->Identification() == aStructId)
246         {
247           hasResult = Standard_True;
248           myStructsComputed.ChangeValue (aToCompStructIter) = aCompStruct;
249           break;
250         }
251       }
252
253       if (!hasResult)
254       {
255         myStructsToCompute.Append (aStruct);
256         myStructsComputed .Append (aCompStruct);
257       }
258
259       aCompStruct->CalculateBoundBox();
260       eraseStructure   (aStruct->CStructure());
261       displayStructure (aCompStruct->CStructure(), aStruct->DisplayPriority());
262     }
263   }
264   Update();
265 }
266
267 // =======================================================================
268 // function : ReCompute
269 // purpose  :
270 // =======================================================================
271 void Graphic3d_CView::ReCompute (const Handle(Graphic3d_Structure)& theStruct)
272 {
273   theStruct->CalculateBoundBox();
274   if (!theStruct->IsMutable()
275    && !theStruct->CStructure()->IsForHighlight
276    && !theStruct->CStructure()->IsInfinite)
277   {
278     const Graphic3d_ZLayerId aLayerId = theStruct->GetZLayer();
279     InvalidateBVHData (aLayerId);
280   }
281
282   if (!ComputedMode()
283    || !IsActive()
284    || !theStruct->IsDisplayed())
285   {
286     return;
287   }
288
289   const Graphic3d_TypeOfAnswer anAnswer = acceptDisplay (theStruct->Visual());
290   if (anAnswer != Graphic3d_TOA_COMPUTE)
291   {
292     return;
293   }
294
295   const Standard_Integer anIndex = IsComputed (theStruct);
296   if (anIndex == 0)
297   {
298     return;
299   }
300
301   // compute + validation
302   Handle(Graphic3d_Structure) aCompStructOld = myStructsComputed.ChangeValue (anIndex);
303   Handle(Graphic3d_Structure) aCompStruct    = aCompStructOld;
304   aCompStruct->SetTransformation (Handle(TopLoc_Datum3D)());
305   theStruct->computeHLR (myCamera, aCompStruct);
306   aCompStruct->SetHLRValidation (Standard_True);
307   aCompStruct->CalculateBoundBox();
308
309   // of which type will be the computed?
310   const Standard_Boolean toComputeWireframe = myVisualization == Graphic3d_TOV_WIREFRAME
311                                            && theStruct->ComputeVisual() != Graphic3d_TOS_SHADING;
312   const Standard_Boolean toComputeShading   = myVisualization == Graphic3d_TOV_SHADING
313                                            && theStruct->ComputeVisual() != Graphic3d_TOS_WIREFRAME;
314   if (toComputeWireframe)
315   {
316     aCompStruct->SetVisual (Graphic3d_TOS_WIREFRAME);
317   }
318   else if (toComputeShading)
319   {
320     aCompStruct->SetVisual (Graphic3d_TOS_SHADING);
321   }
322
323   if (theStruct->IsHighlighted())
324   {
325     aCompStruct->Highlight (theStruct->HighlightStyle(), Standard_False);
326   }
327
328   // The previous calculation is removed and the new one is displayed
329   eraseStructure   (aCompStructOld->CStructure());
330   displayStructure (aCompStruct->CStructure(), theStruct->DisplayPriority());
331
332   // why not just replace existing items?
333   //myStructsToCompute.ChangeValue (anIndex) = theStruct;
334   //myStructsComputed .ChangeValue (anIndex) = aCompStruct;
335
336   // hlhsr and the new associated compute are added
337   myStructsToCompute.Append (theStruct);
338   myStructsComputed .Append (aCompStruct);
339
340   // hlhsr and the new associated compute are removed
341   myStructsToCompute.Remove (anIndex);
342   myStructsComputed .Remove (anIndex);
343 }
344
345 // =======================================================================
346 // function : Update
347 // purpose  :
348 // =======================================================================
349 void Graphic3d_CView::Update (const Graphic3d_ZLayerId theLayerId)
350 {
351   InvalidateZLayerBoundingBox (theLayerId);
352 }
353
354 // =======================================================================
355 // function : InvalidateZLayerBoundingBox
356 // purpose  :
357 // =======================================================================
358 void Graphic3d_CView::InvalidateZLayerBoundingBox (const Graphic3d_ZLayerId theLayerId)
359 {
360   if (Handle(Graphic3d_Layer) aLayer = Layer (theLayerId))
361   {
362     aLayer->InvalidateBoundingBox();
363     return;
364   }
365
366   for (NCollection_List<Handle(Graphic3d_Layer)>::Iterator aLayerIter (Layers()); aLayerIter.More(); aLayerIter.Next())
367   {
368     const Handle(Graphic3d_Layer)& aLayer = aLayerIter.Value();
369     if (aLayer->NbOfTransformPersistenceObjects() > 0)
370     {
371       aLayer->InvalidateBoundingBox();
372     }
373   }
374 }
375
376 // =======================================================================
377 // function : ContainsFacet
378 // purpose  :
379 // =======================================================================
380 Standard_Boolean Graphic3d_CView::ContainsFacet() const
381 {
382   for (Graphic3d_MapOfStructure::Iterator aStructIter (myStructsDisplayed); aStructIter.More(); aStructIter.Next())
383   {
384     if (aStructIter.Key()->ContainsFacet())
385     {
386       return Standard_True;
387     }
388   }
389   return Standard_False;
390 }
391
392 // =======================================================================
393 // function : ContainsFacet
394 // purpose  :
395 // =======================================================================
396 Standard_Boolean Graphic3d_CView::ContainsFacet (const Graphic3d_MapOfStructure& theSet) const
397 {
398   for (Graphic3d_MapIteratorOfMapOfStructure aStructIter (theSet); aStructIter.More(); aStructIter.Next())
399   {
400     if (aStructIter.Key()->ContainsFacet())
401     {
402       return Standard_True;
403     }
404   }
405   return Standard_False;
406 }
407
408 // =======================================================================
409 // function : DisplayedStructures
410 // purpose  :
411 // =======================================================================
412 void Graphic3d_CView::DisplayedStructures (Graphic3d_MapOfStructure& theStructures) const
413 {
414   for (Graphic3d_MapOfStructure::Iterator aStructIter (myStructsDisplayed); aStructIter.More(); aStructIter.Next())
415   {
416     theStructures.Add (aStructIter.Key());
417   }
418 }
419
420 // =======================================================================
421 // function : MinMaxValues
422 // purpose  :
423 // =======================================================================
424 Bnd_Box Graphic3d_CView::MinMaxValues (const Standard_Boolean theToIncludeAuxiliary) const
425 {
426   if (!IsDefined())
427   {
428     return Bnd_Box();
429   }
430
431   const Handle(Graphic3d_Camera)& aCamera = Camera();
432   Graphic3d_Vec2i aWinSize;
433   Window()->Size (aWinSize.x(), aWinSize.y());
434
435   Bnd_Box aResult;
436   for (NCollection_List<Handle(Graphic3d_Layer)>::Iterator aLayerIter (Layers()); aLayerIter.More(); aLayerIter.Next())
437   {
438     const Handle(Graphic3d_Layer)& aLayer = aLayerIter.Value();
439     Bnd_Box aBox = aLayer->BoundingBox (Identification(),
440                                         aCamera,
441                                         aWinSize.x(), aWinSize.y(),
442                                         theToIncludeAuxiliary);
443     aResult.Add (aBox);
444   }
445   return aResult;
446 }
447
448 // =======================================================================
449 // function : ConsiderZoomPersistenceObjects
450 // purpose  :
451 // =======================================================================
452 Standard_Real Graphic3d_CView::ConsiderZoomPersistenceObjects()
453 {
454   if (!IsDefined())
455   {
456     return 1.0;
457   }
458
459   const Handle(Graphic3d_Camera)& aCamera = Camera();
460   Graphic3d_Vec2i aWinSize;
461   Window()->Size (aWinSize.x(), aWinSize.y());
462
463   Standard_Real aMaxCoef = 1.0;
464   for (NCollection_List<Handle(Graphic3d_Layer)>::Iterator aLayerIter (Layers()); aLayerIter.More(); aLayerIter.Next())
465   {
466     const Handle(Graphic3d_Layer)& aLayer = aLayerIter.Value();
467     aMaxCoef = Max (aMaxCoef, aLayer->considerZoomPersistenceObjects (Identification(), aCamera, aWinSize.x(), aWinSize.y()));
468   }
469
470   return aMaxCoef;
471 }
472
473 // =======================================================================
474 // function : MinMaxValues
475 // purpose  :
476 // =======================================================================
477 Bnd_Box Graphic3d_CView::MinMaxValues (const Graphic3d_MapOfStructure& theSet,
478                                        const Standard_Boolean theToIgnoreInfiniteFlag) const
479 {
480   Bnd_Box aResult;
481   const Standard_Integer aViewId = Identification();
482
483   Handle(Graphic3d_Camera) aCamera = Camera();
484   Standard_Integer aWinWidth  = 0;
485   Standard_Integer aWinHeight = 0;
486   if (IsDefined())
487   {
488     Window()->Size (aWinWidth, aWinHeight);
489   }
490
491   for (Graphic3d_MapIteratorOfMapOfStructure aStructIter (theSet); aStructIter.More(); aStructIter.Next())
492   {
493     const Handle(Graphic3d_Structure)& aStructure = aStructIter.Key();
494     if (aStructure->IsEmpty()
495     || !aStructure->CStructure()->IsVisible (aViewId))
496     {
497       continue;
498     }
499
500     // "FitAll" operation ignores object with transform persistence parameter
501     if (!aStructure->TransformPersistence().IsNull())
502     {
503       // Panning and 2d persistence apply changes to projection or/and its translation components.
504       // It makes them incompatible with z-fitting algorithm. Ignored by now.
505       if (!theToIgnoreInfiniteFlag
506        || aStructure->TransformPersistence()->IsTrihedronOr2d())
507       {
508         continue;
509       }
510     }
511
512     Bnd_Box aBox = aStructure->MinMaxValues (theToIgnoreInfiniteFlag);
513
514     if (aBox.IsWhole() || aBox.IsVoid())
515     {
516       continue;
517     }
518
519     if (!aStructure->TransformPersistence().IsNull())
520     {
521       const Graphic3d_Mat4d& aProjectionMat = aCamera->ProjectionMatrix();
522       const Graphic3d_Mat4d& aWorldViewMat  = aCamera->OrientationMatrix();
523       aStructure->TransformPersistence()->Apply (aCamera, aProjectionMat, aWorldViewMat, aWinWidth, aWinHeight, aBox);
524     }
525
526     // To prevent float overflow at camera parameters calculation and further
527     // rendering, bounding boxes with at least one vertex coordinate out of
528     // float range are skipped by view fit algorithms
529     if (Abs (aBox.CornerMax().X()) >= ShortRealLast() ||
530         Abs (aBox.CornerMax().Y()) >= ShortRealLast() ||
531         Abs (aBox.CornerMax().Z()) >= ShortRealLast() ||
532         Abs (aBox.CornerMin().X()) >= ShortRealLast() ||
533         Abs (aBox.CornerMin().Y()) >= ShortRealLast() ||
534         Abs (aBox.CornerMin().Z()) >= ShortRealLast())
535     {
536       continue;
537     }
538
539     aResult.Add (aBox);
540   }
541   return aResult;
542 }
543
544 // =======================================================================
545 // function : acceptDisplay
546 // purpose  :
547 // =======================================================================
548 Graphic3d_TypeOfAnswer Graphic3d_CView::acceptDisplay (const Graphic3d_TypeOfStructure theStructType) const
549 {
550   switch (theStructType)
551   {
552     case Graphic3d_TOS_ALL:
553     {
554       return Graphic3d_TOA_YES; // The structure accepts any type of view
555     }
556     case Graphic3d_TOS_SHADING:
557     {
558       return myVisualization == Graphic3d_TOV_SHADING
559            ? Graphic3d_TOA_YES
560            : Graphic3d_TOA_NO;
561     }
562     case Graphic3d_TOS_WIREFRAME:
563     {
564       return myVisualization == Graphic3d_TOV_WIREFRAME
565            ? Graphic3d_TOA_YES
566            : Graphic3d_TOA_NO;
567     }
568     case Graphic3d_TOS_COMPUTED:
569     {
570       return (myVisualization == Graphic3d_TOV_SHADING || myVisualization == Graphic3d_TOV_WIREFRAME)
571            ?  Graphic3d_TOA_COMPUTE
572            :  Graphic3d_TOA_NO;
573     }
574   }
575   return Graphic3d_TOA_NO;
576 }
577
578 // =======================================================================
579 // function : Compute
580 // purpose  :
581 // =======================================================================
582 void Graphic3d_CView::Compute()
583 {
584   // force HLRValidation to False on all structures calculated in the view
585   for (Graphic3d_SequenceOfStructure::Iterator aStructIter (myStructsComputed); aStructIter.More(); aStructIter.Next())
586   {
587     aStructIter.Value()->SetHLRValidation (Standard_False);
588   }
589
590   if (!ComputedMode())
591   {
592     return;
593   }
594
595   // Change of orientation or of projection type =>
596   // Remove structures that were calculated for the previous orientation.
597   // Recalculation of new structures.
598   NCollection_Sequence<Handle(Graphic3d_Structure)> aStructsSeq;
599   for (Graphic3d_MapOfStructure::Iterator aStructIter (myStructsDisplayed); aStructIter.More(); aStructIter.Next())
600   {
601     const Graphic3d_TypeOfAnswer anAnswer = acceptDisplay (aStructIter.Key()->Visual());
602     if (anAnswer == Graphic3d_TOA_COMPUTE)
603     {
604       aStructsSeq.Append (aStructIter.Key()); // if the structure was calculated, it is recalculated
605     }
606   }
607
608   for (NCollection_Sequence<Handle(Graphic3d_Structure)>::Iterator aStructIter (aStructsSeq); aStructIter.More(); aStructIter.Next())
609   {
610     Display (aStructIter.ChangeValue());
611   }
612 }
613
614 // =======================================================================
615 // function : Clear
616 // purpose  :
617 // =======================================================================
618 void Graphic3d_CView::Clear (Graphic3d_Structure* theStructure,
619                              const Standard_Boolean theWithDestruction)
620 {
621   const Standard_Integer anIndex = IsComputed (theStructure);
622   if (anIndex != 0)
623   {
624     const Handle(Graphic3d_Structure)& aCompStruct = myStructsComputed.Value (anIndex);
625     aCompStruct->GraphicClear (theWithDestruction);
626     aCompStruct->SetHLRValidation (Standard_False);
627   }
628 }
629
630 // =======================================================================
631 // function : Connect
632 // purpose  :
633 // =======================================================================
634 void Graphic3d_CView::Connect (const Graphic3d_Structure* theMother,
635                                const Graphic3d_Structure* theDaughter)
636 {
637   Standard_Integer anIndexM = IsComputed (theMother);
638   Standard_Integer anIndexD = IsComputed (theDaughter);
639   if (anIndexM != 0
640    && anIndexD != 0)
641   {
642     const Handle(Graphic3d_Structure)& aStructM = myStructsComputed.Value (anIndexM);
643     const Handle(Graphic3d_Structure)& aStructD = myStructsComputed.Value (anIndexD);
644     aStructM->GraphicConnect (aStructD);
645   }
646 }
647
648 // =======================================================================
649 // function : Disconnect
650 // purpose  :
651 // =======================================================================
652 void Graphic3d_CView::Disconnect (const Graphic3d_Structure* theMother,
653                                   const Graphic3d_Structure* theDaughter)
654 {
655   Standard_Integer anIndexM = IsComputed (theMother);
656   Standard_Integer anIndexD = IsComputed (theDaughter);
657   if (anIndexM != 0
658    && anIndexD != 0)
659   {
660     const Handle(Graphic3d_Structure)& aStructM = myStructsComputed.Value (anIndexM);
661     const Handle(Graphic3d_Structure)& aStructD = myStructsComputed.Value (anIndexD);
662     aStructM->GraphicDisconnect (aStructD);
663   }
664 }
665
666 // =======================================================================
667 // function : Display
668 // purpose  :
669 // =======================================================================
670 void Graphic3d_CView::Display (const Handle(Graphic3d_Structure)& theStructure)
671 {
672   if (!IsActive())
673   {
674     return;
675   }
676
677   // If Display on a structure present in the list of calculated structures while it is not
678   // or more, of calculated type =>
679   // - removes it as well as the associated old computed
680   // THis happens when hlhsr becomes again of type e non computed after SetVisual.
681   Standard_Integer anIndex = IsComputed (theStructure);
682   if (anIndex != 0
683    && theStructure->Visual() != Graphic3d_TOS_COMPUTED)
684   {
685     myStructsToCompute.Remove (anIndex);
686     myStructsComputed .Remove (anIndex);
687     anIndex = 0;
688   }
689
690   Graphic3d_TypeOfAnswer anAnswer = acceptDisplay (theStructure->Visual());
691   if (anAnswer == Graphic3d_TOA_NO)
692   {
693     return;
694   }
695
696   if (!ComputedMode())
697   {
698     anAnswer = Graphic3d_TOA_YES;
699   }
700
701   if (anAnswer == Graphic3d_TOA_YES)
702   {
703     if (!myStructsDisplayed.Add (theStructure))
704     {
705       return;
706     }
707
708     theStructure->CalculateBoundBox();
709     displayStructure (theStructure->CStructure(), theStructure->DisplayPriority());
710     Update (theStructure->GetZLayer());
711     return;
712   }
713   else if (anAnswer != Graphic3d_TOA_COMPUTE)
714   {
715     return;
716   }
717
718   if (anIndex != 0)
719   {
720     // Already computed, is COMPUTED still valid?
721     const Handle(Graphic3d_Structure)& anOldStruct = myStructsComputed.Value (anIndex);
722     if (anOldStruct->HLRValidation())
723     {
724       // Case COMPUTED valid, to be displayed
725       if (!myStructsDisplayed.Add (theStructure))
726       {
727         return;
728       }
729
730       displayStructure (anOldStruct->CStructure(), theStructure->DisplayPriority());
731       Update (anOldStruct->GetZLayer());
732       return;
733     }
734     else
735     {
736       // Case COMPUTED invalid
737       // Is there another valid representation?
738       // Find in the sequence of already calculated structures
739       // 1/ Structure having the same Owner as <AStructure>
740       // 2/ That is not <AStructure>
741       // 3/ The COMPUTED which of is valid
742       const Standard_Integer aNewIndex = HaveTheSameOwner (theStructure);
743       if (aNewIndex != 0)
744       {
745         // Case of COMPUTED invalid, WITH a valid of replacement; to be displayed
746         if (!myStructsDisplayed.Add (theStructure))
747         {
748           return;
749         }
750
751         const Handle(Graphic3d_Structure)& aNewStruct = myStructsComputed.Value (aNewIndex);
752         myStructsComputed.SetValue (anIndex, aNewStruct);
753         displayStructure (aNewStruct->CStructure(), theStructure->DisplayPriority());
754         Update (aNewStruct->GetZLayer());
755         return;
756       }
757       else
758       {
759         // Case COMPUTED invalid, WITHOUT a valid of replacement
760         // COMPUTED is removed if displayed
761         if (myStructsDisplayed.Contains (theStructure))
762         {
763           eraseStructure (anOldStruct->CStructure());
764         }
765       }
766     }
767   }
768
769   // Compute + Validation
770   Handle(Graphic3d_Structure) aStruct;
771   if (anIndex != 0)
772   {
773     aStruct = myStructsComputed.Value (anIndex);
774     aStruct->SetTransformation (Handle(TopLoc_Datum3D)());
775   }
776   theStructure->computeHLR (myCamera, aStruct);
777
778   aStruct->SetHLRValidation (Standard_True);
779
780   // TOCOMPUTE and COMPUTED associated to sequences are added
781   myStructsToCompute.Append (theStructure);
782   myStructsComputed .Append (aStruct);
783
784   // The previous are removed if necessary
785   if (anIndex != 0)
786   {
787     myStructsToCompute.Remove (anIndex);
788     myStructsComputed .Remove (anIndex);
789   }
790
791   // Of which type will be the computed?
792   const Standard_Boolean toComputeWireframe = myVisualization == Graphic3d_TOV_WIREFRAME
793                                            && theStructure->ComputeVisual() != Graphic3d_TOS_SHADING;
794   const Standard_Boolean toComputeShading   = myVisualization == Graphic3d_TOV_SHADING
795                                            && theStructure->ComputeVisual() != Graphic3d_TOS_WIREFRAME;
796   if (!toComputeShading && !toComputeWireframe)
797   {
798     anAnswer = Graphic3d_TOA_NO;
799   }
800   else
801   {
802     aStruct->SetVisual (toComputeWireframe ? Graphic3d_TOS_WIREFRAME : Graphic3d_TOS_SHADING);
803     anAnswer = acceptDisplay (aStruct->Visual());
804   }
805
806   if (theStructure->IsHighlighted())
807   {
808     aStruct->Highlight (theStructure->HighlightStyle(), Standard_False);
809   }
810
811   // It is displayed only if the calculated structure
812   // has a proper type corresponding to the one of the view.
813   if (anAnswer == Graphic3d_TOA_NO)
814   {
815     return;
816   }
817
818   myStructsDisplayed.Add (theStructure);
819   displayStructure (aStruct->CStructure(), theStructure->DisplayPriority());
820
821   Update (aStruct->GetZLayer());
822 }
823
824 // =======================================================================
825 // function : Erase
826 // purpose  :
827 // =======================================================================
828 void Graphic3d_CView::Erase (const Handle(Graphic3d_Structure)& theStructure)
829 {
830   if (!IsDisplayed (theStructure))
831   {
832     return;
833   }
834
835   const Graphic3d_TypeOfAnswer anAnswer = myIsInComputedMode ? acceptDisplay (theStructure->Visual()) : Graphic3d_TOA_YES;
836   if (anAnswer != Graphic3d_TOA_COMPUTE)
837   {
838     eraseStructure (theStructure->CStructure());
839   }
840
841   const Standard_Integer anIndex = !myStructsToCompute.IsEmpty() ? IsComputed (theStructure) : 0;
842   if (anIndex != 0)
843   {
844     if (anAnswer == Graphic3d_TOA_COMPUTE
845      && myIsInComputedMode)
846     {
847       const Handle(Graphic3d_Structure)& aCompStruct = myStructsComputed.ChangeValue (anIndex);
848       eraseStructure (aCompStruct->CStructure());
849     }
850     myStructsComputed .Remove (anIndex);
851     myStructsToCompute.Remove (anIndex);
852   }
853
854   myStructsDisplayed.Remove (theStructure);
855   Update (theStructure->GetZLayer());
856 }
857
858 // =======================================================================
859 // function : Highlight
860 // purpose  :
861 // =======================================================================
862 void Graphic3d_CView::Highlight (const Handle(Graphic3d_Structure)& theStructure)
863 {
864   const Standard_Integer anIndex = IsComputed (theStructure);
865   if (anIndex != 0)
866   {
867     const Handle(Graphic3d_Structure)& aCompStruct = myStructsComputed.ChangeValue (anIndex);
868     aCompStruct->Highlight (theStructure->HighlightStyle(), Standard_False);
869   }
870 }
871
872 // =======================================================================
873 // function : SetTransform
874 // purpose  :
875 // =======================================================================
876 void Graphic3d_CView::SetTransform (const Handle(Graphic3d_Structure)& theStructure,
877                                     const Handle(TopLoc_Datum3D)& theTrsf)
878 {
879   const Standard_Integer anIndex = IsComputed (theStructure);
880   if (anIndex != 0)
881   {
882     // Test is somewhat light !
883     // trsf is transferred only if it is :
884     // a translation
885     // a scale
886     if (!theTrsf.IsNull()
887       && (theTrsf->Form() == gp_Translation
888        || theTrsf->Form() == gp_Scale
889        || theTrsf->Form() == gp_CompoundTrsf))
890     {
891       ReCompute (theStructure);
892     }
893     else
894     {
895       const Handle(Graphic3d_Structure)& aCompStruct = myStructsComputed.ChangeValue (anIndex);
896       aCompStruct->GraphicTransform (theTrsf);
897     }
898   }
899
900   theStructure->CalculateBoundBox();
901   if (!theStructure->IsMutable()
902    && !theStructure->CStructure()->IsForHighlight
903    && !theStructure->CStructure()->IsInfinite)
904   {
905     const Graphic3d_ZLayerId aLayerId = theStructure->GetZLayer();
906     InvalidateBVHData (aLayerId);
907   }
908 }
909
910 // =======================================================================
911 // function : UnHighlight
912 // purpose  :
913 // =======================================================================
914 void Graphic3d_CView::UnHighlight (const Handle(Graphic3d_Structure)& theStructure)
915 {
916   Standard_Integer anIndex = IsComputed (theStructure);
917   if (anIndex != 0)
918   {
919     const Handle(Graphic3d_Structure)& aCompStruct = myStructsComputed.ChangeValue (anIndex);
920     aCompStruct->CStructure()->GraphicUnhighlight();
921   }
922 }
923
924 // ========================================================================
925 // function : IsComputed
926 // purpose  :
927 // ========================================================================
928 Standard_Boolean Graphic3d_CView::IsComputed (const Standard_Integer theStructId,
929                                               Handle(Graphic3d_Structure)& theComputedStruct) const
930 {
931   theComputedStruct.Nullify();
932   if (!ComputedMode())
933     return Standard_False;
934
935   const Standard_Integer aNbStructs = myStructsToCompute.Length();
936   for (Standard_Integer aStructIter = 1; aStructIter <= aNbStructs; ++aStructIter)
937   {
938     if (myStructsToCompute.Value (aStructIter)->Identification() == theStructId)
939     {
940       theComputedStruct = myStructsComputed (aStructIter);
941       return Standard_True;
942     }
943   }
944   return Standard_False;
945 }
946
947 // =======================================================================
948 // function : IsComputed
949 // purpose  :
950 // =======================================================================
951 Standard_Integer Graphic3d_CView::IsComputed (const Graphic3d_Structure* theStructure) const
952 {
953   const Standard_Integer aStructId  = theStructure->Identification();
954   Standard_Integer aStructIndex = 1;
955   for (Graphic3d_SequenceOfStructure::Iterator aStructIter (myStructsToCompute); aStructIter.More(); aStructIter.Next(), ++aStructIndex)
956   {
957     const Handle(Graphic3d_Structure)& aStruct = aStructIter.Value();
958     if (aStruct->Identification() == aStructId)
959     {
960       return aStructIndex;
961     }
962   }
963   return 0;
964 }
965
966 // =======================================================================
967 // function : IsDisplayed
968 // purpose  :
969 // =======================================================================
970 Standard_Boolean Graphic3d_CView::IsDisplayed (const Handle(Graphic3d_Structure)& theStructure) const
971 {
972   return myStructsDisplayed.Contains (theStructure);
973 }
974
975 // =======================================================================
976 // function : ChangePriority
977 // purpose  :
978 // =======================================================================
979 void Graphic3d_CView::ChangePriority (const Handle(Graphic3d_Structure)& theStructure,
980                                       const Standard_Integer /*theOldPriority*/,
981                                       const Standard_Integer theNewPriority)
982 {
983   if (!IsActive()
984   ||  !IsDisplayed (theStructure))
985   {
986     return;
987   }
988
989   if (!myIsInComputedMode)
990   {
991     changePriority (theStructure->CStructure(), theNewPriority);
992     return;
993   }
994
995   const Standard_Integer              anIndex  = IsComputed (theStructure);
996   const Handle(Graphic3d_CStructure)& aCStruct = anIndex != 0
997                                                ? myStructsComputed.Value (anIndex)->CStructure()
998                                                : theStructure->CStructure();
999
1000   changePriority (aCStruct, theNewPriority);
1001 }
1002
1003 // =======================================================================
1004 // function : ChangeZLayer
1005 // purpose  :
1006 // =======================================================================
1007 void Graphic3d_CView::ChangeZLayer (const Handle(Graphic3d_Structure)& theStructure,
1008                                     const Graphic3d_ZLayerId theLayerId)
1009 {
1010   if (!IsActive()
1011   ||  !IsDisplayed (theStructure))
1012   {
1013     return;
1014   }
1015
1016   if (!myIsInComputedMode)
1017   {
1018     changeZLayer (theStructure->CStructure(), theLayerId);
1019     return;
1020   }
1021
1022   const Standard_Integer       anIndex  = IsComputed (theStructure);
1023   Handle(Graphic3d_CStructure) aCStruct = anIndex != 0
1024                                        ? myStructsComputed.Value (anIndex)->CStructure()
1025                                        : theStructure->CStructure();
1026
1027   changeZLayer (aCStruct, theLayerId);
1028 }
1029
1030 // =======================================================================
1031 // function : HaveTheSameOwner
1032 // purpose  :
1033 // =======================================================================
1034 Standard_Integer Graphic3d_CView::HaveTheSameOwner (const Handle(Graphic3d_Structure)& theStructure) const
1035 {
1036   // Find in the sequence of already calculated structures
1037   // 1/ Structure with the same Owner as <AStructure>
1038   // 2/ Which is not <AStructure>
1039   // 3/ COMPUTED which of is valid
1040   const Standard_Integer aNbToCompStructs = myStructsToCompute.Length();
1041   for (Standard_Integer aStructIter = 1; aStructIter <= aNbToCompStructs; ++aStructIter)
1042   {
1043     const Handle(Graphic3d_Structure)& aStructToComp = myStructsToCompute.Value (aStructIter);
1044     if (aStructToComp->Owner()          == theStructure->Owner()
1045      && aStructToComp->Identification() != theStructure->Identification())
1046     {
1047       const Handle(Graphic3d_Structure)& aStructComp = myStructsComputed.Value (aStructIter);
1048       if (aStructComp->HLRValidation())
1049       {
1050         return aStructIter;
1051       }
1052     }
1053   }
1054   return 0;
1055 }
1056
1057 // =======================================================================
1058 // function : CopySettings
1059 // purpose  :
1060 // =======================================================================
1061 void Graphic3d_CView::CopySettings (const Handle(Graphic3d_CView)& theOther)
1062 {
1063   ChangeRenderingParams() = theOther->RenderingParams();
1064   SetBackground            (theOther->Background());
1065   SetGradientBackground    (theOther->GradientBackground());
1066   SetBackgroundImage       (theOther->BackgroundImage());
1067   SetBackgroundImageStyle  (theOther->BackgroundImageStyle());
1068   SetTextureEnv            (theOther->TextureEnv());
1069   SetShadingModel          (theOther->ShadingModel());
1070   SetBackfacingModel       (theOther->BackfacingModel());
1071   SetCamera                (new Graphic3d_Camera (theOther->Camera()));
1072   SetLights                (theOther->Lights());
1073   SetClipPlanes            (theOther->ClipPlanes());
1074 }
1075
1076 // =======================================================================
1077 // function : SetShadingModel
1078 // purpose  :
1079 // =======================================================================
1080 void Graphic3d_CView::SetShadingModel (Graphic3d_TypeOfShadingModel theModel)
1081 {
1082   if (theModel == Graphic3d_TOSM_DEFAULT)
1083   {
1084     throw Standard_ProgramError ("Graphic3d_CView::SetShadingModel() - attempt to set invalid Shading Model!");
1085   }
1086
1087   myShadingModel = theModel;
1088 }
1089
1090 // =======================================================================
1091 // function : SetUnitFactor
1092 // purpose  :
1093 // =======================================================================
1094 void Graphic3d_CView::SetUnitFactor (Standard_Real theFactor)
1095 {
1096   if (theFactor <= 0.0)
1097   {
1098     throw Standard_ProgramError ("Graphic3d_CView::SetUnitFactor() - invalid unit factor");
1099   }
1100   myUnitFactor = theFactor;
1101   if (!myXRSession.IsNull())
1102   {
1103     myXRSession->SetUnitFactor (theFactor);
1104   }
1105 }
1106
1107 // =======================================================================
1108 // function : IsActiveXR
1109 // purpose  :
1110 // =======================================================================
1111 bool Graphic3d_CView::IsActiveXR() const
1112 {
1113   return !myXRSession.IsNull()
1114        && myXRSession->IsOpen();
1115 }
1116
1117 // =======================================================================
1118 // function : InitXR
1119 // purpose  :
1120 // =======================================================================
1121 bool Graphic3d_CView::InitXR()
1122 {
1123   if (myXRSession.IsNull())
1124   {
1125     myXRSession = new Aspect_OpenVRSession();
1126     myXRSession->SetUnitFactor (myUnitFactor);
1127   }
1128   if (!myXRSession->IsOpen())
1129   {
1130     myXRSession->Open();
1131     if (myBackXRCamera.IsNull())
1132     {
1133       // backup camera properties
1134       myBackXRCamera = new Graphic3d_Camera (myCamera);
1135     }
1136   }
1137   return myXRSession->IsOpen();
1138 }
1139
1140 // =======================================================================
1141 // function : ReleaseXR
1142 // purpose  :
1143 // =======================================================================
1144 void Graphic3d_CView::ReleaseXR()
1145 {
1146   if (!myXRSession.IsNull())
1147   {
1148     if (myXRSession->IsOpen()
1149     && !myBackXRCamera.IsNull())
1150     {
1151       // restore projection properties overridden by HMD
1152       myCamera->SetFOV2d (myBackXRCamera->FOV2d());
1153       myCamera->SetFOVy  (myBackXRCamera->FOVy());
1154       myCamera->SetAspect(myBackXRCamera->Aspect());
1155       myCamera->SetIOD   (myBackXRCamera->GetIODType(), myBackXRCamera->IOD());
1156       myCamera->SetZFocus(myBackXRCamera->ZFocusType(), myBackXRCamera->ZFocus());
1157       myCamera->ResetCustomProjection();
1158       myBackXRCamera.Nullify();
1159     }
1160     myXRSession->Close();
1161   }
1162 }
1163
1164 //=======================================================================
1165 //function : ProcessXRInput
1166 //purpose  :
1167 //=======================================================================
1168 void Graphic3d_CView::ProcessXRInput()
1169 {
1170   if (myRenderParams.StereoMode == Graphic3d_StereoMode_OpenVR
1171    && myCamera->ProjectionType() == Graphic3d_Camera::Projection_Stereo)
1172   {
1173     InitXR();
1174   }
1175   else
1176   {
1177     ReleaseXR();
1178   }
1179
1180   if (!IsActiveXR())
1181   {
1182     myBaseXRCamera.Nullify();
1183     myPosedXRCamera.Nullify();
1184     return;
1185   }
1186
1187   myXRSession->ProcessEvents();
1188   Invalidate();
1189
1190   myCamera->SetFOV2d (myRenderParams.HmdFov2d);
1191   myCamera->SetAspect(myXRSession->Aspect());
1192   myCamera->SetFOVy  (myXRSession->FieldOfView());
1193   myCamera->SetIOD   (Graphic3d_Camera::IODType_Absolute, myXRSession->IOD());
1194   myCamera->SetZFocus(Graphic3d_Camera::FocusType_Absolute, 1.0 * myUnitFactor);
1195
1196   // VR APIs tend to decompose camera orientation-projection matrices into the following components:
1197   // @begincode
1198   //   Model * [View * Eye^-1] * [Projection]
1199   // @endcode
1200   // so that Eye position is encoded into Orientation matrix, and there should be 2 Orientation matrices and 2 Projection matrices to make the stereo.
1201   // Graphic3d_Camera historically follows different decomposition, with Eye position encoded into Projection matrix,
1202   // so that there is only 1 Orientation matrix (matching mono view) and 2 Projection matrices.
1203   if (myXRSession->HasProjectionFrustums())
1204   {
1205     // note that this definition does not include a small forward/backward offset from head to eye
1206     myCamera->SetCustomStereoFrustums (myXRSession->ProjectionFrustum (Aspect_Eye_Left),
1207                                        myXRSession->ProjectionFrustum (Aspect_Eye_Right));
1208   }
1209   else
1210   {
1211     const Graphic3d_Mat4d aPoseL = myXRSession->HeadToEyeTransform (Aspect_Eye_Left);
1212     const Graphic3d_Mat4d aPoseR = myXRSession->HeadToEyeTransform (Aspect_Eye_Right);
1213     const Graphic3d_Mat4d aProjL = myXRSession->ProjectionMatrix (Aspect_Eye_Left,  myCamera->ZNear(), myCamera->ZFar());
1214     const Graphic3d_Mat4d aProjR = myXRSession->ProjectionMatrix (Aspect_Eye_Right, myCamera->ZNear(), myCamera->ZFar());
1215     myCamera->SetCustomStereoProjection (aProjL * aPoseL, aProjR * aPoseR);
1216   }
1217   myBaseXRCamera = myCamera;
1218   if (myPosedXRCamera.IsNull())
1219   {
1220     myPosedXRCamera = new Graphic3d_Camera();
1221   }
1222   SynchronizeXRBaseToPosedCamera();
1223 }
1224
1225 //=======================================================================
1226 //function : SynchronizeXRBaseToPosedCamera
1227 //purpose  :
1228 //=======================================================================
1229 void Graphic3d_CView::SynchronizeXRBaseToPosedCamera()
1230 {
1231   if (!myPosedXRCamera.IsNull())
1232   {
1233     ComputeXRPosedCameraFromBase (*myPosedXRCamera, myXRSession->HeadPose());
1234   }
1235 }
1236
1237 //=======================================================================
1238 //function : ComputeXRPosedCameraFromBase
1239 //purpose  :
1240 //=======================================================================
1241 void Graphic3d_CView::ComputeXRPosedCameraFromBase (Graphic3d_Camera& theCam,
1242                                                     const gp_Trsf& theXRTrsf) const
1243 {
1244   theCam.Copy (myBaseXRCamera);
1245
1246   // convert head pose into camera transformation
1247   const gp_Ax3 anAxVr    (gp::Origin(),  gp::DZ(), gp::DX());
1248   const gp_Ax3 aCameraCS (gp::Origin(), -myBaseXRCamera->Direction(), -myBaseXRCamera->SideRight());
1249   gp_Trsf aTrsfCS;
1250   aTrsfCS.SetTransformation (aCameraCS, anAxVr);
1251   const gp_Trsf aTrsfToCamera = aTrsfCS * theXRTrsf * aTrsfCS.Inverted();
1252   gp_Trsf aTrsfToEye;
1253   aTrsfToEye.SetTranslation (myBaseXRCamera->Eye().XYZ());
1254
1255   const gp_Trsf aTrsf = aTrsfToEye * aTrsfToCamera;
1256   const gp_Dir anUpNew  = myBaseXRCamera->Up().Transformed (aTrsf);
1257   const gp_Dir aDirNew  = myBaseXRCamera->Direction().Transformed (aTrsf);
1258   const gp_Pnt anEyeNew = gp::Origin().Translated (aTrsf.TranslationPart());
1259   theCam.SetUp (anUpNew);
1260   theCam.SetDirectionFromEye (aDirNew);
1261   theCam.MoveEyeTo (anEyeNew);
1262 }
1263
1264 //=======================================================================
1265 //function : SynchronizeXRPosedToBaseCamera
1266 //purpose  :
1267 //=======================================================================
1268 void Graphic3d_CView::SynchronizeXRPosedToBaseCamera()
1269 {
1270   if (myPosedXRCameraCopy.IsNull()
1271    || myPosedXRCamera.IsNull()
1272    || myBaseXRCamera.IsNull()
1273    || myCamera != myPosedXRCamera)
1274   {
1275     return;
1276   }
1277
1278   if (myPosedXRCameraCopy->Eye().IsEqual (myPosedXRCamera->Eye(), gp::Resolution())
1279    && (myPosedXRCameraCopy->Distance() - myPosedXRCamera->Distance()) <= gp::Resolution()
1280    && myPosedXRCameraCopy->Direction().IsEqual (myPosedXRCamera->Direction(), gp::Resolution())
1281    && myPosedXRCameraCopy->Up().IsEqual (myPosedXRCamera->Up(), gp::Resolution()))
1282   {
1283     // avoid floating point math in case of no changes
1284     return;
1285   }
1286
1287   // re-compute myBaseXRCamera from myPosedXRCamera by applying reversed head pose transformation
1288   ComputeXRBaseCameraFromPosed (myPosedXRCamera, myXRSession->HeadPose());
1289   myPosedXRCameraCopy->Copy (myPosedXRCamera);
1290 }
1291
1292 //=======================================================================
1293 //function : ComputeXRBaseCameraFromPosed
1294 //purpose  :
1295 //=======================================================================
1296 void Graphic3d_CView::ComputeXRBaseCameraFromPosed (const Graphic3d_Camera& theCamPosed,
1297                                                     const gp_Trsf& thePoseTrsf)
1298 {
1299   const gp_Ax3 anAxVr    (gp::Origin(),  gp::DZ(), gp::DX());
1300   const gp_Ax3 aCameraCS (gp::Origin(), -myBaseXRCamera->Direction(), -myBaseXRCamera->SideRight());
1301   gp_Trsf aTrsfCS;
1302   aTrsfCS.SetTransformation (aCameraCS, anAxVr);
1303   const gp_Trsf aTrsfToCamera  = aTrsfCS * thePoseTrsf * aTrsfCS.Inverted();
1304   const gp_Trsf aTrsfCamToHead = aTrsfToCamera.Inverted();
1305   const gp_Dir anUpNew  = theCamPosed.Up().Transformed (aTrsfCamToHead);
1306   const gp_Dir aDirNew  = theCamPosed.Direction().Transformed (aTrsfCamToHead);
1307   const gp_Pnt anEyeNew = theCamPosed.Eye().Translated (aTrsfToCamera.TranslationPart().Reversed());
1308   myBaseXRCamera->SetUp (anUpNew);
1309   myBaseXRCamera->SetDirectionFromEye (aDirNew);
1310   myBaseXRCamera->MoveEyeTo (anEyeNew);
1311 }
1312
1313 //=======================================================================
1314 //function : TurnViewXRCamera
1315 //purpose  :
1316 //=======================================================================
1317 void Graphic3d_CView::TurnViewXRCamera (const gp_Trsf& theTrsfTurn)
1318 {
1319   // use current eye position as an anchor
1320   const Handle(Graphic3d_Camera)& aCamBase = myBaseXRCamera;
1321   gp_Trsf aHeadTrsfLocal;
1322   aHeadTrsfLocal.SetTranslationPart (myXRSession->HeadPose().TranslationPart());
1323   const gp_Pnt anEyeAnchor = PoseXRToWorld (aHeadTrsfLocal).TranslationPart();
1324
1325   // turn the view
1326   aCamBase->SetDirectionFromEye (aCamBase->Direction().Transformed (theTrsfTurn));
1327
1328   // recompute new eye
1329   const gp_Ax3 anAxVr    (gp::Origin(),  gp::DZ(), gp::DX());
1330   const gp_Ax3 aCameraCS (gp::Origin(), -aCamBase->Direction(), -aCamBase->SideRight());
1331   gp_Trsf aTrsfCS;
1332   aTrsfCS.SetTransformation (aCameraCS, anAxVr);
1333   const gp_Trsf aTrsfToCamera = aTrsfCS * aHeadTrsfLocal * aTrsfCS.Inverted();
1334   const gp_Pnt anEyeNew = anEyeAnchor.Translated (aTrsfToCamera.TranslationPart().Reversed());
1335   aCamBase->MoveEyeTo (anEyeNew);
1336
1337   SynchronizeXRBaseToPosedCamera();
1338 }
1339
1340 //=======================================================================
1341 //function : SetupXRPosedCamera
1342 //purpose  :
1343 //=======================================================================
1344 void Graphic3d_CView::SetupXRPosedCamera()
1345 {
1346   if (!myPosedXRCamera.IsNull())
1347   {
1348     myCamera = myPosedXRCamera;
1349     if (myPosedXRCameraCopy.IsNull())
1350     {
1351       myPosedXRCameraCopy = new Graphic3d_Camera();
1352     }
1353     myPosedXRCameraCopy->Copy (myPosedXRCamera);
1354   }
1355 }
1356
1357 //=======================================================================
1358 //function : UnsetXRPosedCamera
1359 //purpose  :
1360 //=======================================================================
1361 void Graphic3d_CView::UnsetXRPosedCamera()
1362 {
1363   if (myCamera == myPosedXRCamera
1364   && !myBaseXRCamera.IsNull())
1365   {
1366     SynchronizeXRPosedToBaseCamera();
1367     myCamera = myBaseXRCamera;
1368   }
1369 }
1370
1371 //=======================================================================
1372 //function : DiagnosticInformation
1373 //purpose  :
1374 //=======================================================================
1375 void Graphic3d_CView::DiagnosticInformation (TColStd_IndexedDataMapOfStringString& theDict,
1376                                              Graphic3d_DiagnosticInfo theFlags) const
1377 {
1378   if ((theFlags & Graphic3d_DiagnosticInfo_Device) != 0
1379    && !myXRSession.IsNull())
1380   {
1381     TCollection_AsciiString aVendor  = myXRSession->GetString (Aspect_XRSession::InfoString_Vendor);
1382     TCollection_AsciiString aDevice  = myXRSession->GetString (Aspect_XRSession::InfoString_Device);
1383     TCollection_AsciiString aTracker = myXRSession->GetString (Aspect_XRSession::InfoString_Tracker);
1384     TCollection_AsciiString aSerial  = myXRSession->GetString (Aspect_XRSession::InfoString_SerialNumber);
1385     TCollection_AsciiString aDisplay = TCollection_AsciiString()
1386                                      + myXRSession->RecommendedViewport().x() + "x" + myXRSession->RecommendedViewport().y()
1387                                      + "@" + (int )Round (myXRSession->DisplayFrequency())
1388                                      + " [FOVy: " + (int )Round (myXRSession->FieldOfView()) + "]";
1389
1390     theDict.ChangeFromIndex (theDict.Add ("VRvendor",  aVendor))  = aVendor;
1391     theDict.ChangeFromIndex (theDict.Add ("VRdevice",  aDevice))  = aDevice;
1392     theDict.ChangeFromIndex (theDict.Add ("VRtracker", aTracker)) = aTracker;
1393     theDict.ChangeFromIndex (theDict.Add ("VRdisplay", aDisplay)) = aDisplay;
1394     theDict.ChangeFromIndex (theDict.Add ("VRserial",  aSerial))  = aSerial;
1395   }
1396 }