0022819: Redesign of OpenGl driver
[occt.git] / src / OpenGl / OpenGl_Group.cxx
1 // File:      OpenGl_Group.cxx
2 // Created:   1 August 2011
3 // Author:    Sergey ZERCHANINOV
4 // Copyright: OPEN CASCADE 2011
5
6 #include <OpenGl_Group.hxx>
7
8 #include <OpenGl_TextureBox.hxx>
9 #include <OpenGl_PrimitiveArray.hxx>
10
11 /*----------------------------------------------------------------------*/
12
13 OpenGl_Group::OpenGl_Group ()
14 : myAspectLine(NULL),
15   myAspectFace(NULL),
16   myAspectMarker(NULL),
17   myAspectText(NULL),
18   myFirst(NULL), myLast(NULL)
19 {
20 }
21
22 OpenGl_Group::~OpenGl_Group()
23 {
24   Clear();
25 }
26
27 /*----------------------------------------------------------------------*/
28
29 void OpenGl_Group::SetAspectLine (const CALL_DEF_CONTEXTLINE& theContext,
30                                   const Standard_Boolean theIsGlobal)
31 {
32   if (theIsGlobal || myFirst == NULL)
33   {
34     if (myAspectLine == NULL)
35       myAspectLine = new OpenGl_AspectLine();
36     myAspectLine->SetContext (theContext);
37   }
38   else
39   {
40     OpenGl_AspectLine* anAspectLine = new OpenGl_AspectLine();
41     anAspectLine->SetContext (theContext);
42     AddElement (TelNil/*TelAspectLine*/, anAspectLine);
43   }
44 }
45
46 /*----------------------------------------------------------------------*/
47
48 void OpenGl_Group::SetAspectFace (const CALL_DEF_CONTEXTFILLAREA& theContext,
49                                   const Standard_Boolean theIsGlobal)
50 {
51   if (theIsGlobal || myFirst == NULL)
52   {
53     if (myAspectFace == NULL)
54       myAspectFace = new OpenGl_AspectFace();
55     myAspectFace->SetContext (theContext);
56   }
57   else
58   {
59     OpenGl_AspectFace* anAspectFace = new OpenGl_AspectFace();
60     anAspectFace->SetContext (theContext);
61     AddElement (TelNil/*TelAspectFace*/, anAspectFace);
62   }
63 }
64
65 /*----------------------------------------------------------------------*/
66
67 void OpenGl_Group::SetAspectMarker (const CALL_DEF_CONTEXTMARKER& theContext,
68                                     const Standard_Boolean theIsGlobal)
69 {
70   if (theIsGlobal || myFirst == NULL)
71   {
72     if (myAspectMarker == NULL)
73       myAspectMarker = new OpenGl_AspectMarker();
74     myAspectMarker->SetContext (theContext);
75   }
76   else
77   {
78     OpenGl_AspectMarker* anAspectMarker = new OpenGl_AspectMarker();
79     anAspectMarker->SetContext (theContext);
80     AddElement (TelNil/*TelAspectMarker*/, anAspectMarker);
81   }
82 }
83
84 /*----------------------------------------------------------------------*/
85
86 void OpenGl_Group::SetAspectText (const CALL_DEF_CONTEXTTEXT& theContext,
87                                   const Standard_Boolean theIsGlobal)
88 {
89   if (theIsGlobal || myFirst == NULL)
90   {
91     if (myAspectText == NULL)
92       myAspectText = new OpenGl_AspectText();
93     myAspectText->SetContext (theContext);
94   }
95   else
96   {
97     OpenGl_AspectText* anAspectText = new OpenGl_AspectText();
98     anAspectText->SetContext (theContext);
99     AddElement ( TelNil/*TelAspectText*/, anAspectText);
100   }
101 }
102
103 /*----------------------------------------------------------------------*/
104
105 void OpenGl_Group::AddElement (const TelType AType, OpenGl_Element *AElem )
106 {
107   OpenGl_ElementNode *node = new OpenGl_ElementNode();
108
109   node->type = AType;
110   node->elem = AElem;
111   node->next = NULL;
112   (myLast? myLast->next : myFirst) = node;
113   myLast = node;
114 }
115
116 /*----------------------------------------------------------------------*/
117
118 void OpenGl_Group::Clear ()
119 {
120   if (myAspectLine)
121   {
122     // Delete line context
123     delete myAspectLine;
124     myAspectLine = NULL;
125   }
126   if (myAspectFace)
127   {
128     // Delete face context
129     delete myAspectFace;
130     myAspectFace = NULL;
131   }
132   if (myAspectMarker)
133   {
134     // Delete marker context
135     delete myAspectMarker;
136     myAspectMarker = NULL;
137   }
138   if (myAspectText)
139   {
140     // Delete text context
141     delete myAspectText;
142     myAspectText = NULL;
143   }
144   // Delete elements
145   while (myFirst)
146   {
147     OpenGl_ElementNode *next = myFirst->next;
148     delete myFirst->elem;
149     delete myFirst;
150     myFirst = next;
151   }
152   myLast = NULL;
153 }
154
155 /*----------------------------------------------------------------------*/
156
157 void OpenGl_Group::RemovePrimitiveArray (CALL_DEF_PARRAY *APArray)
158 {
159   OpenGl_ElementNode *prevnode = NULL, *node = myFirst;
160   while (node)
161   {
162     if (node->type == TelParray)
163     {
164       CALL_DEF_PARRAY *aCurPArray = ((const OpenGl_PrimitiveArray *)node->elem)->PArray();
165
166       // validate for correct pointer
167       if (aCurPArray->num_bounds  == APArray->num_bounds  && 
168           aCurPArray->num_edges   == APArray->num_edges   &&
169           aCurPArray->num_vertexs == APArray->num_vertexs &&
170           aCurPArray->type        == APArray->type)
171       {
172         (prevnode? prevnode->next : myFirst) = node->next;
173         if (!myFirst) myLast = NULL;
174         delete node->elem;
175         delete node;
176         break;
177       }
178     }
179     prevnode = node;
180     node = node->next;
181   }
182 }
183
184 /*----------------------------------------------------------------------*/
185
186 void OpenGl_Group::Render (const Handle(OpenGl_Workspace) &AWorkspace) const
187 {
188   // Is rendering in ADD or IMMEDIATE mode?
189   const Standard_Boolean isImmediate = (AWorkspace->NamedStatus & (OPENGL_NS_ADD | OPENGL_NS_IMMEDIATE)) != 0;
190
191   // Setup aspects
192   const OpenGl_AspectLine *aspect_line = AWorkspace->AspectLine(Standard_False);
193   const OpenGl_AspectFace *aspect_face = AWorkspace->AspectFace(Standard_False);
194   const OpenGl_AspectMarker *aspect_marker = AWorkspace->AspectMarker(Standard_False);
195   const OpenGl_AspectText *aspect_text = AWorkspace->AspectText(Standard_False);
196   if (myAspectLine)
197     AWorkspace->SetAspectLine(myAspectLine);
198   if (myAspectFace)
199     AWorkspace->SetAspectFace(myAspectFace);
200   if (myAspectMarker)
201     AWorkspace->SetAspectMarker(myAspectMarker);
202   if (myAspectText)
203     AWorkspace->SetAspectText(myAspectText);
204
205   // Render group elements
206   OpenGl_ElementNode *node = myFirst;
207   while (node)
208   {
209     switch (node->type)
210     {
211       case TelPolyline:
212       case TelMarker:
213       case TelMarkerSet:
214       case TelText:
215       {
216         glDisable(GL_LIGHTING);
217
218         if (isImmediate)
219         {
220           glDepthMask(GL_FALSE);
221         }
222         else if ( (AWorkspace->NamedStatus & OPENGL_NS_ANIMATION) != 0 &&
223                   (AWorkspace->NamedStatus & OPENGL_NS_WIREFRAME) == 0 &&
224                    AWorkspace->DegenerateModel != 0 )
225         {
226           glDisable( GL_DEPTH_TEST );
227           if ( AWorkspace->NamedStatus & OPENGL_NS_TEXTURE ) DisableTexture();
228           AWorkspace->NamedStatus |= OPENGL_NS_WIREFRAME;
229         }
230
231         node->elem->Render( AWorkspace );
232
233         if ( !isImmediate && (AWorkspace->NamedStatus & OPENGL_NS_TEXTURE) != 0 ) EnableTexture();
234         break;
235       }
236
237       case TelPolygon:
238       case TelPolygonIndices:
239       case TelQuadrangle:
240       case TelTriangleMesh:
241       {
242         if (isImmediate)
243         {
244           glDepthMask(GL_FALSE);
245         }
246         else if ( (AWorkspace->NamedStatus & OPENGL_NS_ANIMATION) != 0 &&
247                   (AWorkspace->NamedStatus & OPENGL_NS_WIREFRAME) != 0 &&
248                   AWorkspace->DegenerateModel < 2 )
249         {
250           if ( AWorkspace->NamedStatus & OPENGL_NS_TEXTURE ) EnableTexture ();
251
252           glEnable( GL_DEPTH_TEST );
253           AWorkspace->NamedStatus &= ~OPENGL_NS_WIREFRAME;
254         }
255
256         if ( AWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT )
257           AWorkspace->DisablePolygonOffset();
258
259         node->elem->Render( AWorkspace );
260
261         if ( AWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT )
262           AWorkspace->EnablePolygonOffset();
263         break;
264       }
265
266       default:
267       {
268         node->elem->Render( AWorkspace );
269         break;
270       }
271     }
272     node = node->next;
273   }
274
275   // Restore aspects
276   AWorkspace->SetAspectLine(aspect_line);
277   AWorkspace->SetAspectFace(aspect_face);
278   AWorkspace->SetAspectMarker(aspect_marker);
279   AWorkspace->SetAspectText(aspect_text);
280 }
281
282 /*----------------------------------------------------------------------*/