0031687: Draw Harness, ViewerTest - extend command vrenderparams with option updating...
[occt.git] / src / AIS / AIS_CameraFrustum.cxx
1 // Created on: 2018-12-12
2 // Created by: Olga SURYANINOVA
3 // Copyright (c) 2018 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 under
8 // the terms of the GNU Lesser General Public License 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 <AIS_CameraFrustum.hxx>
17
18 #include <AIS_DisplayMode.hxx>
19 #include <Graphic3d_ArrayOfTriangles.hxx>
20 #include <Graphic3d_ArrayOfSegments.hxx>
21 #include <Prs3d_LineAspect.hxx>
22 #include <Prs3d_ShadingAspect.hxx>
23 #include <Select3D_SensitiveGroup.hxx>
24 #include <Select3D_SensitivePrimitiveArray.hxx>
25 #include <Select3D_SensitiveSegment.hxx>
26 #include <SelectMgr_EntityOwner.hxx>
27
28 IMPLEMENT_STANDARD_RTTIEXT(AIS_CameraFrustum, AIS_InteractiveObject)
29
30 namespace
31 {
32   static const Standard_ShortReal THE_DEFAULT_TRANSPARENCY = 0.7f;
33   static const Quantity_Color     THE_DEFAULT_COLOR = Quantity_NOC_WHITE;
34 }
35
36 //=======================================================================
37 //function : Constructor
38 //purpose  :
39 //=======================================================================
40 AIS_CameraFrustum::AIS_CameraFrustum()
41 : myPoints (0, Graphic3d_Camera::FrustumVerticesNB)
42 {
43   myDrawer->SetLineAspect (new Prs3d_LineAspect (THE_DEFAULT_COLOR, Aspect_TOL_SOLID, 1.0));
44
45   Handle(Prs3d_ShadingAspect) aShadingAspect = new Prs3d_ShadingAspect();
46   aShadingAspect->SetMaterial (Graphic3d_NOM_PLASTIC);
47   aShadingAspect->Aspect()->SetAlphaMode (Graphic3d_AlphaMode_Blend);
48   aShadingAspect->SetTransparency (THE_DEFAULT_TRANSPARENCY);
49   aShadingAspect->SetColor (THE_DEFAULT_COLOR);
50   myDrawer->SetShadingAspect (aShadingAspect);
51
52   myDrawer->SetTransparency (THE_DEFAULT_TRANSPARENCY);
53   SetDisplayMode (AIS_Shaded);
54 }
55
56 //=======================================================================
57 //function : AcceptDisplayMode
58 //purpose  :
59 //=======================================================================
60 Standard_Boolean AIS_CameraFrustum::AcceptDisplayMode (const Standard_Integer theMode) const
61 {
62   return theMode == AIS_Shaded || theMode == AIS_WireFrame;
63 }
64
65 //=======================================================================
66 //function : SetCameraFrustum
67 //purpose  :
68 //=======================================================================
69 void AIS_CameraFrustum::SetCameraFrustum (const Handle(Graphic3d_Camera)& theCamera)
70 {
71   if (theCamera.IsNull())
72   {
73     return;
74   }
75
76   theCamera->FrustumPoints (myPoints);
77
78   fillTriangles();
79   fillBorders();
80
81   SetToUpdate();
82 }
83
84 //=======================================================================
85 //function : SetColor
86 //purpose  :
87 //=======================================================================
88 void AIS_CameraFrustum::SetColor (const Quantity_Color& theColor)
89 {
90   AIS_InteractiveObject::SetColor (theColor);
91   myDrawer->ShadingAspect()->SetColor (theColor);
92   myDrawer->LineAspect()->SetColor (theColor);
93   SynchronizeAspects();
94 }
95
96 //=======================================================================
97 //function : UnsetColor
98 //purpose  :
99 //=======================================================================
100 void AIS_CameraFrustum::UnsetColor()
101 {
102   if (!HasColor())
103   {
104     return;
105   }
106
107   AIS_InteractiveObject::UnsetColor();
108
109   myDrawer->ShadingAspect()->SetColor (THE_DEFAULT_COLOR);
110   myDrawer->LineAspect()->SetColor (THE_DEFAULT_COLOR);
111   SynchronizeAspects();
112 }
113
114 //=======================================================================
115 //function : UnsetColor
116 //purpose  :
117 //=======================================================================
118 void AIS_CameraFrustum::UnsetTransparency()
119 {
120   myDrawer->ShadingAspect()->SetTransparency (0.0f);
121   myDrawer->SetTransparency (0.0f);
122   SynchronizeAspects();
123 }
124
125 //=======================================================================
126 //function : fillTriangles
127 //purpose  :
128 //=======================================================================
129 void AIS_CameraFrustum::fillTriangles()
130 {
131   if (myTriangles.IsNull())
132   {
133     const Standard_Integer aPlaneTriangleVertsNb = 2 * 3;
134     const Standard_Integer aPlanesNb             = 3 * 2;
135
136     myTriangles = new Graphic3d_ArrayOfTriangles (Graphic3d_Camera::FrustumVerticesNB, aPlaneTriangleVertsNb * aPlanesNb);
137     myTriangles->SetVertice (Graphic3d_Camera::FrustumVerticesNB, gp_Pnt (0.0, 0.0, 0.0));
138
139     // Triangles go in order (clockwise vertices traversing for correct normal):
140     // (0, 2, 1), (3, 1, 2)
141     const Standard_Integer aLookup1_clockwise[]     = { 0, 1, 0, 1, 0, 1 };
142     const Standard_Integer aLookup2_clockwise[]     = { 0, 0, 1, 1, 1, 0 };
143     // Triangles go in order (counterclockwise vertices traversing for correct normal):
144     // (1, 2, 0), (2, 1, 3)
145     const Standard_Integer aLookup1_anticlockwise[] = { 0, 1, 0, 1, 0, 1 };
146     const Standard_Integer aLookup2_anticlockwise[] = { 1, 0, 0, 0, 1, 1 };
147     Standard_Integer aShifts[]        = { 0, 0, 0 };
148
149     // Planes go in order:
150     // LEFT, RIGHT, BOTTOM, TOP, NEAR, FAR
151     for (Standard_Integer aFaceIdx = 0; aFaceIdx < 3; ++aFaceIdx)
152     {
153       for (Standard_Integer i = 0; i < 2; ++i)
154       {
155         for (Standard_Integer aPntIter = 0; aPntIter < aPlaneTriangleVertsNb; ++aPntIter)
156         {
157           aShifts[aFaceIdx] = i;
158           if (i == 0)
159           {
160             aShifts[(aFaceIdx + 1) % 3] = aLookup1_clockwise[aPntIter];
161             aShifts[(aFaceIdx + 2) % 3] = aLookup2_clockwise[aPntIter];
162           }
163           else
164           {
165             aShifts[(aFaceIdx + 1) % 3] = aLookup1_anticlockwise[aPntIter];
166             aShifts[(aFaceIdx + 2) % 3] = aLookup2_anticlockwise[aPntIter];
167           }
168
169           Standard_Integer anIndex = aShifts[0] * 2 * 2 + aShifts[1] * 2 + aShifts[2];
170           myTriangles->AddEdge (anIndex + 1);
171         }
172       }
173     }
174   }
175
176   for (Standard_Integer aPointIter = 0; aPointIter < Graphic3d_Camera::FrustumVerticesNB; ++aPointIter)
177   {
178     const Graphic3d_Vec3d aPnt = myPoints[aPointIter];
179     myTriangles->SetVertice (aPointIter + 1, gp_Pnt (aPnt.x(), aPnt.y(), aPnt.z()));
180   }
181 }
182
183 //=======================================================================
184 //function : fillBorders
185 //purpose  :
186 //=======================================================================
187 void AIS_CameraFrustum::fillBorders()
188 {
189   if (myBorders.IsNull())
190   {
191     const Standard_Integer aPlaneSegmVertsNb = 2 * 4;
192     const Standard_Integer aPlanesNb         = 3 * 2;
193     myBorders = new Graphic3d_ArrayOfSegments (Graphic3d_Camera::FrustumVerticesNB, aPlaneSegmVertsNb * aPlanesNb);
194     myBorders->SetVertice (Graphic3d_Camera::FrustumVerticesNB, gp_Pnt (0.0, 0.0, 0.0));
195
196     // Segments go in order:
197     // (0, 2), (2, 3), (3, 1), (1, 0)
198     const Standard_Integer aLookup1[] = { 0, 1, 1, 1, 1, 0, 0, 0 };
199     const Standard_Integer aLookup2[] = { 0, 0, 0, 1, 1, 1, 1, 0 };
200     Standard_Integer aShifts[] = { 0, 0, 0 };
201
202     // Planes go in order:
203     // LEFT, RIGHT, BOTTOM, TOP, NEAR, FAR
204     for (Standard_Integer aFaceIdx = 0; aFaceIdx < 3; ++aFaceIdx)
205     {
206       for (Standard_Integer i = 0; i < 2; ++i)
207       {
208         for (Standard_Integer aSegmVertIter = 0; aSegmVertIter < aPlaneSegmVertsNb; ++aSegmVertIter)
209         {
210           aShifts[aFaceIdx] = i;
211           aShifts[(aFaceIdx + 1) % 3] = aLookup1[aSegmVertIter];
212           aShifts[(aFaceIdx + 2) % 3] = aLookup2[aSegmVertIter];
213
214           Standard_Integer anIndex = aShifts[0] * 2 * 2 + aShifts[1] * 2 + aShifts[2];
215           myBorders->AddEdge (anIndex + 1);
216         }
217       }
218     }
219   }
220
221   for (Standard_Integer aPointIter = 0; aPointIter < Graphic3d_Camera::FrustumVerticesNB; ++aPointIter)
222   {
223     const Graphic3d_Vec3d aPnt = myPoints[aPointIter];
224     myBorders->SetVertice (aPointIter + 1, gp_Pnt (aPnt.x(), aPnt.y(), aPnt.z()));
225   }
226 }
227
228 //=======================================================================
229 //function : Compute
230 //purpose  :
231 //=======================================================================
232 void AIS_CameraFrustum::Compute (const Handle(PrsMgr_PresentationManager3d)& ,
233                                  const Handle(Prs3d_Presentation)&           thePrs,
234                                  const Standard_Integer                      theMode)
235 {
236   thePrs->SetInfiniteState (true);
237   if (myTriangles.IsNull())
238   {
239     return;
240   }
241
242   switch (theMode)
243   {
244     case AIS_Shaded:
245     {
246       Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
247       aGroup->SetGroupPrimitivesAspect (myDrawer->ShadingAspect()->Aspect());
248       aGroup->AddPrimitiveArray (myTriangles);
249     }
250     Standard_FALLTHROUGH
251     case AIS_WireFrame:
252     {
253       Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
254       aGroup->SetGroupPrimitivesAspect (myDrawer->LineAspect()->Aspect());
255       aGroup->AddPrimitiveArray (myBorders);
256       break;
257     }
258   }
259 }
260
261 //=======================================================================
262 //function : ComputeSelection
263 //purpose  :
264 //=======================================================================
265 void AIS_CameraFrustum::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
266                                           const Standard_Integer             theMode)
267 {
268   Handle(SelectMgr_EntityOwner) anOwner = new SelectMgr_EntityOwner (this);
269   switch (theMode)
270   {
271     case SelectionMode_Edges:
272     {
273       Handle(Select3D_SensitiveGroup) aSensitiveEntity = new Select3D_SensitiveGroup (anOwner);
274       for (Standard_Integer anIter = 1; anIter <= myBorders->EdgeNumber(); anIter += 2)
275       {
276         aSensitiveEntity->Add (new Select3D_SensitiveSegment (anOwner, myBorders->Vertice (myBorders->Edge (anIter)), myBorders->Vertice(myBorders->Edge (anIter + 1))));
277       }
278       theSelection->Add (aSensitiveEntity);
279       break;
280     }
281     case SelectionMode_Volume:
282     {
283       Handle(Select3D_SensitivePrimitiveArray) aSelArray = new Select3D_SensitivePrimitiveArray (anOwner);
284       aSelArray->InitTriangulation (myTriangles->Attributes(), myTriangles->Indices(), TopLoc_Location());
285       theSelection->Add (aSelArray);
286       break;
287     }
288   }
289 }