0023188: Regression in SCATexturedShape in SSP sample
[occt.git] / src / OpenGl / OpenGl_Group.cxx
1 // Created on: 2011-08-01
2 // Created by: Sergey ZERCHANINOV
3 // Copyright (c) 2011-2012 OPEN CASCADE SAS
4 //
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
9 //
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12 //
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
19
20
21 #include <OpenGl_Group.hxx>
22
23 #include <OpenGl_TextureBox.hxx>
24 #include <OpenGl_PrimitiveArray.hxx>
25
26 /*----------------------------------------------------------------------*/
27
28 OpenGl_Group::OpenGl_Group ()
29 : myAspectLine(NULL),
30   myAspectFace(NULL),
31   myAspectMarker(NULL),
32   myAspectText(NULL),
33   myFirst(NULL), myLast(NULL)
34 {
35 }
36
37 OpenGl_Group::~OpenGl_Group()
38 {
39   Clear();
40 }
41
42 /*----------------------------------------------------------------------*/
43
44 void OpenGl_Group::SetAspectLine (const CALL_DEF_CONTEXTLINE& theContext,
45                                   const Standard_Boolean theIsGlobal)
46 {
47   if (theIsGlobal || myFirst == NULL)
48   {
49     if (myAspectLine == NULL)
50       myAspectLine = new OpenGl_AspectLine();
51     myAspectLine->SetContext (theContext);
52   }
53   else
54   {
55     OpenGl_AspectLine* anAspectLine = new OpenGl_AspectLine();
56     anAspectLine->SetContext (theContext);
57     AddElement (TelNil/*TelAspectLine*/, anAspectLine);
58   }
59 }
60
61 /*----------------------------------------------------------------------*/
62
63 void OpenGl_Group::SetAspectFace (const CALL_DEF_CONTEXTFILLAREA& theContext,
64                                   const Standard_Boolean theIsGlobal)
65 {
66   if (theIsGlobal || myFirst == NULL)
67   {
68     if (myAspectFace == NULL)
69       myAspectFace = new OpenGl_AspectFace();
70     myAspectFace->SetContext (theContext);
71   }
72   else
73   {
74     OpenGl_AspectFace* anAspectFace = new OpenGl_AspectFace();
75     anAspectFace->SetContext (theContext);
76     AddElement (TelNil/*TelAspectFace*/, anAspectFace);
77   }
78 }
79
80 /*----------------------------------------------------------------------*/
81
82 void OpenGl_Group::SetAspectMarker (const CALL_DEF_CONTEXTMARKER& theContext,
83                                     const Standard_Boolean theIsGlobal)
84 {
85   if (theIsGlobal || myFirst == NULL)
86   {
87     if (myAspectMarker == NULL)
88       myAspectMarker = new OpenGl_AspectMarker();
89     myAspectMarker->SetContext (theContext);
90   }
91   else
92   {
93     OpenGl_AspectMarker* anAspectMarker = new OpenGl_AspectMarker();
94     anAspectMarker->SetContext (theContext);
95     AddElement (TelNil/*TelAspectMarker*/, anAspectMarker);
96   }
97 }
98
99 /*----------------------------------------------------------------------*/
100
101 void OpenGl_Group::SetAspectText (const CALL_DEF_CONTEXTTEXT& theContext,
102                                   const Standard_Boolean theIsGlobal)
103 {
104   if (theIsGlobal || myFirst == NULL)
105   {
106     if (myAspectText == NULL)
107       myAspectText = new OpenGl_AspectText();
108     myAspectText->SetContext (theContext);
109   }
110   else
111   {
112     OpenGl_AspectText* anAspectText = new OpenGl_AspectText();
113     anAspectText->SetContext (theContext);
114     AddElement ( TelNil/*TelAspectText*/, anAspectText);
115   }
116 }
117
118 /*----------------------------------------------------------------------*/
119
120 void OpenGl_Group::AddElement (const TelType AType, OpenGl_Element *AElem )
121 {
122   OpenGl_ElementNode *node = new OpenGl_ElementNode();
123
124   node->type = AType;
125   node->elem = AElem;
126   node->next = NULL;
127   (myLast? myLast->next : myFirst) = node;
128   myLast = node;
129 }
130
131 /*----------------------------------------------------------------------*/
132
133 void OpenGl_Group::Clear ()
134 {
135   if (myAspectLine)
136   {
137     // Delete line context
138     delete myAspectLine;
139     myAspectLine = NULL;
140   }
141   if (myAspectFace)
142   {
143     // Delete face context
144     delete myAspectFace;
145     myAspectFace = NULL;
146   }
147   if (myAspectMarker)
148   {
149     // Delete marker context
150     delete myAspectMarker;
151     myAspectMarker = NULL;
152   }
153   if (myAspectText)
154   {
155     // Delete text context
156     delete myAspectText;
157     myAspectText = NULL;
158   }
159   // Delete elements
160   while (myFirst)
161   {
162     OpenGl_ElementNode *next = myFirst->next;
163     delete myFirst->elem;
164     delete myFirst;
165     myFirst = next;
166   }
167   myLast = NULL;
168 }
169
170 /*----------------------------------------------------------------------*/
171
172 void OpenGl_Group::RemovePrimitiveArray (CALL_DEF_PARRAY *APArray)
173 {
174   OpenGl_ElementNode *prevnode = NULL, *node = myFirst;
175   while (node)
176   {
177     if (node->type == TelParray)
178     {
179       CALL_DEF_PARRAY *aCurPArray = ((const OpenGl_PrimitiveArray *)node->elem)->PArray();
180
181       // validate for correct pointer
182       if (aCurPArray->num_bounds  == APArray->num_bounds  && 
183           aCurPArray->num_edges   == APArray->num_edges   &&
184           aCurPArray->num_vertexs == APArray->num_vertexs &&
185           aCurPArray->type        == APArray->type)
186       {
187         (prevnode? prevnode->next : myFirst) = node->next;
188         if (!myFirst) myLast = NULL;
189         delete node->elem;
190         delete node;
191         break;
192       }
193     }
194     prevnode = node;
195     node = node->next;
196   }
197 }
198
199 /*----------------------------------------------------------------------*/
200
201 void OpenGl_Group::Render (const Handle(OpenGl_Workspace) &AWorkspace) const
202 {
203   // Is rendering in ADD or IMMEDIATE mode?
204   const Standard_Boolean isImmediate = (AWorkspace->NamedStatus & (OPENGL_NS_ADD | OPENGL_NS_IMMEDIATE)) != 0;
205
206   // Setup aspects
207   const OpenGl_AspectLine *aspect_line = AWorkspace->AspectLine(Standard_False);
208   const OpenGl_AspectFace *aspect_face = AWorkspace->AspectFace(Standard_False);
209   const OpenGl_AspectMarker *aspect_marker = AWorkspace->AspectMarker(Standard_False);
210   const OpenGl_AspectText *aspect_text = AWorkspace->AspectText(Standard_False);
211   if (myAspectLine)
212     AWorkspace->SetAspectLine(myAspectLine);
213   if (myAspectFace)
214     AWorkspace->SetAspectFace(myAspectFace);
215   if (myAspectMarker)
216     AWorkspace->SetAspectMarker(myAspectMarker);
217   if (myAspectText)
218     AWorkspace->SetAspectText(myAspectText);
219
220   // Render group elements
221   OpenGl_ElementNode *node = myFirst;
222   while (node)
223   {
224     switch (node->type)
225     {
226       case TelPolyline:
227       case TelMarker:
228       case TelMarkerSet:
229       case TelText:
230       {
231         glDisable(GL_LIGHTING);
232
233         if (isImmediate)
234         {
235           glDepthMask(GL_FALSE);
236         }
237         else if ( (AWorkspace->NamedStatus & OPENGL_NS_ANIMATION) != 0 &&
238                   (AWorkspace->NamedStatus & OPENGL_NS_WIREFRAME) == 0 &&
239                    AWorkspace->DegenerateModel != 0 )
240         {
241           glDisable( GL_DEPTH_TEST );
242           if ( AWorkspace->NamedStatus & OPENGL_NS_TEXTURE ) DisableTexture();
243           AWorkspace->NamedStatus |= OPENGL_NS_WIREFRAME;
244         }
245
246         node->elem->Render( AWorkspace );
247
248         if ( !isImmediate && (AWorkspace->NamedStatus & OPENGL_NS_TEXTURE) != 0 ) EnableTexture();
249         break;
250       }
251
252       case TelPolygon:
253       case TelPolygonIndices:
254       case TelQuadrangle:
255       case TelTriangleMesh:
256       {
257         if (isImmediate)
258         {
259           glDepthMask(GL_FALSE);
260         }
261         else if ( (AWorkspace->NamedStatus & OPENGL_NS_ANIMATION) != 0 &&
262                   (AWorkspace->NamedStatus & OPENGL_NS_WIREFRAME) != 0 &&
263                   AWorkspace->DegenerateModel < 2 )
264         {
265           if ( AWorkspace->NamedStatus & OPENGL_NS_TEXTURE ) EnableTexture ();
266
267           glEnable( GL_DEPTH_TEST );
268           AWorkspace->NamedStatus &= ~OPENGL_NS_WIREFRAME;
269         }
270
271         if ( AWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT )
272           AWorkspace->DisablePolygonOffset();
273
274         node->elem->Render( AWorkspace );
275
276         if ( AWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT )
277           AWorkspace->EnablePolygonOffset();
278         break;
279       }
280
281       default:
282       {
283         node->elem->Render( AWorkspace );
284         break;
285       }
286     }
287     node = node->next;
288   }
289
290   // Restore aspects
291   AWorkspace->SetAspectLine(aspect_line);
292   AWorkspace->SetAspectFace(aspect_face);
293   AWorkspace->SetAspectMarker(aspect_marker);
294   AWorkspace->SetAspectText(aspect_text);
295 }
296
297 /*----------------------------------------------------------------------*/