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