0024271: Provide Boolean operations for NCollection_Map
[occt.git] / src / OpenGl / OpenGl_Structure.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 #include <OpenGl_GlCore11.hxx>
21
22 #include <OpenGl_Structure.hxx>
23
24 #include <OpenGl_Workspace.hxx>
25 #include <OpenGl_Vec.hxx>
26 #include <OpenGl_View.hxx>
27 #include <OpenGl_CappingAlgo.hxx>
28 #include <OpenGl_Context.hxx>
29 #include <OpenGl_telem_util.hxx>
30
31 #include <Graphic3d_SetOfHClipPlane_Handle.hxx>
32
33 //! Auxiliary class for bounding box presentation
34 class OpenGl_BndBoxPrs : public OpenGl_Element
35 {
36
37 public:
38
39   //! Main constructor
40   OpenGl_BndBoxPrs (const CALL_DEF_BOUNDBOX& theBndBox)
41   {
42     const float Xm = theBndBox.Pmin.x;
43     const float Ym = theBndBox.Pmin.y;
44     const float Zm = theBndBox.Pmin.z;
45     const float XM = theBndBox.Pmax.x;
46     const float YM = theBndBox.Pmax.y;
47     const float ZM = theBndBox.Pmax.z;
48     myVerts[0]  = OpenGl_Vec3 (Xm, Ym, Zm);
49     myVerts[1]  = OpenGl_Vec3 (Xm, Ym, ZM);
50     myVerts[2]  = OpenGl_Vec3 (Xm, YM, ZM);
51     myVerts[3]  = OpenGl_Vec3 (Xm, YM, Zm);
52     myVerts[4]  = OpenGl_Vec3 (Xm, Ym, Zm);
53     myVerts[5]  = OpenGl_Vec3 (XM, Ym, Zm);
54     myVerts[6]  = OpenGl_Vec3 (XM, Ym, ZM);
55     myVerts[7]  = OpenGl_Vec3 (XM, YM, ZM);
56     myVerts[8]  = OpenGl_Vec3 (XM, YM, Zm);
57     myVerts[9]  = OpenGl_Vec3 (XM, Ym, Zm);
58     myVerts[10] = OpenGl_Vec3 (XM, YM, Zm);
59     myVerts[11] = OpenGl_Vec3 (Xm, YM, Zm);
60     myVerts[12] = OpenGl_Vec3 (Xm, YM, ZM);
61     myVerts[13] = OpenGl_Vec3 (XM, YM, ZM);
62     myVerts[14] = OpenGl_Vec3 (XM, Ym, ZM);
63     myVerts[15] = OpenGl_Vec3 (Xm, Ym, ZM);
64   }
65
66   //! Render presentation
67   virtual void Render  (const Handle(OpenGl_Workspace)& theWorkspace) const
68   {
69     // Apply line aspect
70     const OpenGl_AspectLine*     anAspectLine = theWorkspace->AspectLine (Standard_True);
71     const Handle(OpenGl_Texture) aPrevTexture = theWorkspace->DisableTexture();
72
73     glDisable (GL_LIGHTING);
74     if ((theWorkspace->NamedStatus & (OPENGL_NS_ADD | OPENGL_NS_IMMEDIATE)) != 0)
75     {
76       glDepthMask (GL_FALSE);
77     }
78
79     // Use highlight colors
80     glColor3fv ((theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT) ? theWorkspace->HighlightColor->rgb : anAspectLine->Color().rgb);
81
82     glEnableClientState (GL_VERTEX_ARRAY);
83     glVertexPointer (3, GL_FLOAT, 0, (GLfloat* )&myVerts);
84     glDrawArrays (GL_LINE_STRIP, 0, 16);
85     glDisableClientState (GL_VERTEX_ARRAY);
86
87     // restore aspects
88     if (!aPrevTexture.IsNull())
89     {
90       theWorkspace->EnableTexture (aPrevTexture);
91     }
92   }
93
94   //! Release graphical resources
95   virtual void Release (const Handle(OpenGl_Context)& )
96   {
97     //
98   }
99
100 protected:
101
102   //! Protected destructor
103   virtual ~OpenGl_BndBoxPrs() {}
104
105 private:
106
107   OpenGl_Vec3 myVerts[16]; //!< vertices array
108
109 public:
110
111   DEFINE_STANDARD_ALLOC
112
113 };
114
115 /*----------------------------------------------------------------------*/
116
117 // =======================================================================
118 // function : call_util_transpose_mat
119 // purpose  :
120 // =======================================================================
121 static void call_util_transpose_mat (float tmat[16], float mat[4][4])
122 {
123   int i, j;
124
125   for (i=0; i<4; i++)
126     for (j=0; j<4; j++)
127       tmat[j*4+i] = mat[i][j];
128 }
129
130 // =======================================================================
131 // function : OpenGl_Structure
132 // purpose  :
133 // =======================================================================
134 OpenGl_Structure::OpenGl_Structure ()
135 : myTransformation(NULL),
136   myTransPers(NULL),
137   myAspectLine(NULL),
138   myAspectFace(NULL),
139   myAspectMarker(NULL),
140   myAspectText(NULL),
141   myHighlightBox(NULL),
142   myHighlightColor(NULL),
143   myNamedStatus(0),
144   myZLayer(0)
145 {
146 }
147
148 // =======================================================================
149 // function : ~OpenGl_Structure
150 // purpose  :
151 // =======================================================================
152 OpenGl_Structure::~OpenGl_Structure()
153 {
154   Release (Handle(OpenGl_Context)());
155   delete myTransformation;  myTransformation  = NULL;
156   delete myTransPers;       myTransPers       = NULL;
157 }
158
159 // =======================================================================
160 // function : SetTransformation
161 // purpose  :
162 // =======================================================================
163 void OpenGl_Structure::SetTransformation(const float *AMatrix)
164 {
165   if (!myTransformation)
166     myTransformation = new OpenGl_Matrix();
167
168   matcpy( myTransformation->mat, AMatrix );
169 }
170
171 // =======================================================================
172 // function : SetTransformPersistence
173 // purpose  :
174 // =======================================================================
175 void OpenGl_Structure::SetTransformPersistence(const CALL_DEF_TRANSFORM_PERSISTENCE &ATransPers)
176 {
177   if (!myTransPers)
178     myTransPers = new TEL_TRANSFORM_PERSISTENCE;
179
180   myTransPers->mode = ATransPers.Flag;
181   myTransPers->pointX = ATransPers.Point.x;
182   myTransPers->pointY = ATransPers.Point.y;
183   myTransPers->pointZ = ATransPers.Point.z;
184 }
185
186 // =======================================================================
187 // function : SetAspectLine
188 // purpose  :
189 // =======================================================================
190 void OpenGl_Structure::SetAspectLine (const CALL_DEF_CONTEXTLINE &AContext)
191 {
192   if (!myAspectLine)
193     myAspectLine = new OpenGl_AspectLine();
194   myAspectLine->SetContext( AContext );
195 }
196
197 // =======================================================================
198 // function : SetAspectFace
199 // purpose  :
200 // =======================================================================
201 void OpenGl_Structure::SetAspectFace (const Handle(OpenGl_Context)&   theCtx,
202                                       const CALL_DEF_CONTEXTFILLAREA& theAspect)
203 {
204   if (!myAspectFace)
205   {
206     myAspectFace = new OpenGl_AspectFace();
207   }
208   myAspectFace->Init (theCtx, theAspect);
209 }
210
211 // =======================================================================
212 // function : SetAspectMarker
213 // purpose  :
214 // =======================================================================
215 void OpenGl_Structure::SetAspectMarker (const Handle(OpenGl_Context)& theCtx,
216                                         const CALL_DEF_CONTEXTMARKER& theAspect)
217 {
218   if (!myAspectMarker)
219   {
220     myAspectMarker = new OpenGl_AspectMarker();
221   }
222   myAspectMarker->Init (theCtx, theAspect);
223 }
224
225 // =======================================================================
226 // function : SetAspectText
227 // purpose  :
228 // =======================================================================
229 void OpenGl_Structure::SetAspectText (const CALL_DEF_CONTEXTTEXT &AContext)
230 {
231   if (!myAspectText)
232     myAspectText = new OpenGl_AspectText();
233   myAspectText->SetContext( AContext );
234 }
235
236 // =======================================================================
237 // function : SetHighlightBox
238 // purpose  :
239 // =======================================================================
240 void OpenGl_Structure::SetHighlightBox (const Handle(OpenGl_Context)& theGlCtx,
241                                         const CALL_DEF_BOUNDBOX&      theBoundBox)
242 {
243   if (myHighlightBox != NULL)
244   {
245     myHighlightBox->Release (theGlCtx);
246   }
247   else
248   {
249     myHighlightBox = new OpenGl_Group();
250   }
251
252   CALL_DEF_CONTEXTLINE aContextLine;
253   aContextLine.Color    = theBoundBox.Color;
254   aContextLine.LineType = Aspect_TOL_SOLID;
255   aContextLine.Width    = 1.0f;
256   myHighlightBox->SetAspectLine (aContextLine);
257
258   OpenGl_BndBoxPrs* aBndBoxPrs = new OpenGl_BndBoxPrs (theBoundBox);
259   myHighlightBox->AddElement (TelParray, aBndBoxPrs);
260 }
261
262 // =======================================================================
263 // function : ClearHighlightBox
264 // purpose  :
265 // =======================================================================
266 void OpenGl_Structure::ClearHighlightBox (const Handle(OpenGl_Context)& theGlCtx)
267 {
268   if (myHighlightBox != NULL)
269   {
270     OpenGl_Element::Destroy (theGlCtx, myHighlightBox);
271   }
272 }
273
274 // =======================================================================
275 // function : SetHighlightColor
276 // purpose  :
277 // =======================================================================
278 void OpenGl_Structure::SetHighlightColor (const Handle(OpenGl_Context)& theGlCtx,
279                                           const Standard_ShortReal R,
280                                           const Standard_ShortReal G,
281                                           const Standard_ShortReal B)
282 {
283   ClearHighlightBox (theGlCtx);
284   if (myHighlightColor == NULL)
285   {
286     myHighlightColor = new TEL_COLOUR();
287   }
288
289   myHighlightColor->rgb[0] = R;
290   myHighlightColor->rgb[1] = G;
291   myHighlightColor->rgb[2] = B;
292   myHighlightColor->rgb[3] = 1.F;
293 }
294
295 // =======================================================================
296 // function : ClearHighlightColor
297 // purpose  :
298 // =======================================================================
299 void OpenGl_Structure::ClearHighlightColor (const Handle(OpenGl_Context)& theGlCtx)
300 {
301   ClearHighlightBox(theGlCtx);
302   delete myHighlightColor;
303   myHighlightColor = NULL;
304 }
305
306 // =======================================================================
307 // function : Connect
308 // purpose  :
309 // =======================================================================
310 void OpenGl_Structure::Connect (const OpenGl_Structure *AStructure)
311 {
312   Disconnect (AStructure);
313   myConnected.Append(AStructure);
314 }
315
316 // =======================================================================
317 // function : Disconnect
318 // purpose  :
319 // =======================================================================
320 void OpenGl_Structure::Disconnect (const OpenGl_Structure *AStructure)
321 {
322   OpenGl_ListOfStructure::Iterator its(myConnected);
323   while (its.More())
324   {
325     // Check for the given structure
326     if (its.Value() == AStructure)
327     {
328       myConnected.Remove(its);
329       return;
330     }
331     its.Next();
332   }
333 }
334
335 // =======================================================================
336 // function : AddGroup
337 // purpose  :
338 // =======================================================================
339 OpenGl_Group * OpenGl_Structure::AddGroup ()
340 {
341   // Create new group
342   OpenGl_Group *g = new OpenGl_Group;
343   myGroups.Append(g);
344   return g;
345 }
346
347 // =======================================================================
348 // function : RemoveGroup
349 // purpose  :
350 // =======================================================================
351 void OpenGl_Structure::RemoveGroup (const Handle(OpenGl_Context)& theGlCtx,
352                                     const OpenGl_Group*           theGroup)
353 {
354   for (OpenGl_ListOfGroup::Iterator anIter (myGroups); anIter.More(); anIter.Next())
355   {
356     // Check for the given group
357     if (anIter.Value() == theGroup)
358     {
359       // Delete object
360       OpenGl_Element::Destroy (theGlCtx, const_cast<OpenGl_Group*& > (anIter.ChangeValue()));
361       myGroups.Remove (anIter);
362       return;
363     }
364   }
365 }
366
367 // =======================================================================
368 // function : Clear
369 // purpose  :
370 // =======================================================================
371 void OpenGl_Structure::Clear (const Handle(OpenGl_Context)& theGlCtx)
372 {
373   // Release groups
374   for (OpenGl_ListOfGroup::Iterator anIter (myGroups); anIter.More(); anIter.Next())
375   {
376     // Delete objects
377     OpenGl_Element::Destroy (theGlCtx, const_cast<OpenGl_Group*& > (anIter.ChangeValue()));
378   }
379   myGroups.Clear();
380 }
381
382 // =======================================================================
383 // function : Render
384 // purpose  :
385 // =======================================================================
386 void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &AWorkspace) const
387 {
388   // Process the structure only if visible
389   if ( myNamedStatus & OPENGL_NS_HIDE )
390     return;
391
392   // Render named status
393   const Standard_Integer named_status = AWorkspace->NamedStatus;
394   AWorkspace->NamedStatus |= myNamedStatus;
395
396   // Is rendering in ADD or IMMEDIATE mode?
397   const Standard_Boolean isImmediate = (AWorkspace->NamedStatus & (OPENGL_NS_ADD | OPENGL_NS_IMMEDIATE)) != 0;
398
399   // Apply local transformation
400   GLint matrix_mode = 0;
401   const OpenGl_Matrix *local_trsf = NULL;
402   if (myTransformation)
403   {
404     if (isImmediate)
405     {
406       float mat16[16];
407       call_util_transpose_mat (mat16, myTransformation->mat);
408       glGetIntegerv (GL_MATRIX_MODE, &matrix_mode);
409       glMatrixMode (GL_MODELVIEW);
410       glPushMatrix ();
411       glScalef (1.F, 1.F, 1.F);
412       glMultMatrixf (mat16);
413     }
414     else
415     {
416       glMatrixMode (GL_MODELVIEW);
417       glPushMatrix();
418
419       local_trsf = AWorkspace->SetStructureMatrix(myTransformation);
420     }
421   }
422
423   // Apply transform persistence
424   const TEL_TRANSFORM_PERSISTENCE *trans_pers = NULL;
425   if ( myTransPers && myTransPers->mode != 0 )
426   {
427     trans_pers = AWorkspace->ActiveView()->BeginTransformPersistence( myTransPers );
428   }
429
430   // Apply aspects
431   const OpenGl_AspectLine *aspect_line = AWorkspace->AspectLine(Standard_False);
432   const OpenGl_AspectFace *aspect_face = AWorkspace->AspectFace(Standard_False);
433   const OpenGl_AspectMarker *aspect_marker = AWorkspace->AspectMarker(Standard_False);
434   const OpenGl_AspectText *aspect_text = AWorkspace->AspectText(Standard_False);
435   if (myAspectLine)
436     AWorkspace->SetAspectLine(myAspectLine);
437   if (myAspectFace)
438     AWorkspace->SetAspectFace(myAspectFace);
439   if (myAspectMarker)
440     AWorkspace->SetAspectMarker(myAspectMarker);
441   if (myAspectText)
442     AWorkspace->SetAspectText(myAspectText);
443
444   // Apply highlight box
445   if (myHighlightBox)
446     myHighlightBox->Render( AWorkspace );
447
448   // Apply highlight color
449   const TEL_COLOUR *highlight_color = AWorkspace->HighlightColor;
450   if (myHighlightColor)
451     AWorkspace->HighlightColor = myHighlightColor;
452
453   // Render connected structures
454   OpenGl_ListOfStructure::Iterator its(myConnected);
455   while (its.More())
456   {
457     its.Value()->Render(AWorkspace);
458     its.Next();
459   }
460
461   // Set up plane equations for non-structure transformed global model-view matrix
462   const Handle(OpenGl_Context)& aContext = AWorkspace->GetGlContext();
463
464   // List of planes to be applied to context state
465   Handle(Graphic3d_SetOfHClipPlane) aUserPlanes;
466
467   // Collect clipping planes of structure scope
468   if (!myClipPlanes.IsEmpty())
469   {
470     Graphic3d_SetOfHClipPlane::Iterator aClippingIt (myClipPlanes);
471     for (; aClippingIt.More(); aClippingIt.Next())
472     {
473       const Handle(Graphic3d_ClipPlane)& aClipPlane = aClippingIt.Value();
474       if (!aClipPlane->IsOn())
475       {
476         continue;
477       }
478
479       if (aUserPlanes.IsNull())
480       {
481         aUserPlanes = new Graphic3d_SetOfHClipPlane();
482       }
483
484       aUserPlanes->Add (aClipPlane);
485     }
486   }
487
488   if (!aUserPlanes.IsNull() && !aUserPlanes->IsEmpty())
489   {
490     // add planes at loaded view matrix state
491     aContext->ChangeClipping().AddWorld (*aUserPlanes, AWorkspace);
492   }
493
494   // Render groups
495   OpenGl_ListOfGroup::Iterator itg(myGroups);
496   while (itg.More())
497   {
498     itg.Value()->Render(AWorkspace);
499     itg.Next();
500   }
501
502   // Render capping for structure groups
503   if (!aContext->Clipping().Planes().IsEmpty())
504   {
505     OpenGl_CappingAlgo::RenderCapping (AWorkspace, myGroups);
506   }
507
508   // Revert structure clippings
509   if (!aUserPlanes.IsNull() && !aUserPlanes->IsEmpty())
510   {
511     aContext->ChangeClipping().Remove (*aUserPlanes);
512   }
513
514   // Restore highlight color
515   AWorkspace->HighlightColor = highlight_color;
516
517   // Restore aspects
518   AWorkspace->SetAspectLine(aspect_line);
519   AWorkspace->SetAspectFace(aspect_face);
520   AWorkspace->SetAspectMarker(aspect_marker);
521   AWorkspace->SetAspectText(aspect_text);
522
523   // Restore transform persistence
524   if ( myTransPers && myTransPers->mode != 0 )
525   {
526     AWorkspace->ActiveView()->BeginTransformPersistence( trans_pers );
527   }
528
529   // Restore local transformation
530   if (myTransformation)
531   {
532     if (isImmediate)
533     {
534       glPopMatrix ();
535       glMatrixMode (matrix_mode);
536     }
537     else
538     {
539       AWorkspace->SetStructureMatrix(local_trsf);
540
541       glMatrixMode (GL_MODELVIEW);
542       glPopMatrix();
543     }
544   }
545
546   // Restore named status
547   AWorkspace->NamedStatus = named_status;
548 }
549
550 // =======================================================================
551 // function : Release
552 // purpose  :
553 // =======================================================================
554 void OpenGl_Structure::Release (const Handle(OpenGl_Context)& theGlCtx)
555 {
556   // Release groups
557   Clear (theGlCtx);
558   OpenGl_Element::Destroy (theGlCtx, myAspectLine);
559   OpenGl_Element::Destroy (theGlCtx, myAspectFace);
560   OpenGl_Element::Destroy (theGlCtx, myAspectMarker);
561   OpenGl_Element::Destroy (theGlCtx, myAspectText);
562   ClearHighlightColor (theGlCtx);
563 }
564
565 // =======================================================================
566 // function : ReleaseGlResources
567 // purpose  :
568 // =======================================================================
569 void OpenGl_Structure::ReleaseGlResources (const Handle(OpenGl_Context)& theGlCtx)
570 {
571   for (OpenGl_ListOfGroup::Iterator anIter (myGroups); anIter.More(); anIter.Next())
572   {
573     OpenGl_Group* aGroup = const_cast<OpenGl_Group*& > (anIter.ChangeValue());
574     if (aGroup != NULL)
575     {
576       aGroup->Release (theGlCtx);
577     }
578   }
579   if (myAspectLine != NULL)
580   {
581     myAspectLine->Release (theGlCtx);
582   }
583   if (myAspectFace != NULL)
584   {
585     myAspectFace->Release (theGlCtx);
586   }
587   if (myAspectMarker != NULL)
588   {
589     myAspectMarker->Release (theGlCtx);
590   }
591   if (myAspectText != NULL)
592   {
593     myAspectText->Release (theGlCtx);
594   }
595   if (myHighlightBox != NULL)
596   {
597     myHighlightBox->Release (theGlCtx);
598   }
599 }
600
601 //=======================================================================
602 //function : SetZLayer
603 //purpose  :
604 //=======================================================================
605 void OpenGl_Structure::SetZLayer (const Standard_Integer theLayerIndex)
606 {
607   myZLayer = theLayerIndex;
608 }
609
610 //=======================================================================
611 //function : GetZLayer
612 //purpose  :
613 //=======================================================================
614 Standard_Integer OpenGl_Structure::GetZLayer () const
615 {
616   return myZLayer;
617 }