e25d821d24f27bacfc048d7430222f0d43c85852
[occt.git] / src / OpenGl / OpenGl_Trihedron.cxx
1 // Created on: 2011-09-20
2 // Created by: Sergey ZERCHANINOV
3 // Copyright (c) 2011-2014 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 <OpenGl_Trihedron.hxx>
17
18 #include <OpenGl_GlCore11.hxx>
19
20 #include <Graphic3d_ArrayOfSegments.hxx>
21 #include <Graphic3d_ArrayOfPolylines.hxx>
22 #include <Graphic3d_GraphicDriver.hxx>
23 #include <Graphic3d_TransformUtils.hxx>
24 #include <OpenGl_View.hxx>
25 #include <OpenGl_Workspace.hxx>
26 #include <Precision.hxx>
27
28 namespace
29 {
30   static const OpenGl_TextParam THE_LABEL_PARAMS =
31   {
32     16, Graphic3d_HTA_LEFT, Graphic3d_VTA_BOTTOM
33   };
34 }
35
36 // =======================================================================
37 // function : resetTransformations
38 // purpose  :
39 // =======================================================================
40 void OpenGl_Trihedron::resetTransformations (const Handle(OpenGl_Workspace)& theWorkspace) const
41 {
42   const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
43   const OpenGl_View*            aView    = theWorkspace->View();
44   GLdouble anU = 1.0;
45   GLdouble aV = 1.0;
46   if (aView->Height() < aView->Width())
47   {
48     aV = aView->Width() / aView->Height();
49   }
50   else
51   {
52     anU = aView->Height() / aView->Width();
53   }
54
55   // Reading the transformation matrices and projection of sight
56   // to cancel translations (last columns of matrices).
57   OpenGl_Mat4d aModelMatrix;
58   OpenGl_Mat4d aProjMatrix;
59   aModelMatrix.Convert (aContext->WorldViewState.Current());
60
61   // Cancel the translation that can be assigned to the view
62   aModelMatrix.ChangeValue (0, 3) = 0.0;
63   aModelMatrix.ChangeValue (1, 3) = 0.0;
64   aModelMatrix.ChangeValue (2, 3) = 0.0;
65
66   aProjMatrix.ChangeValue (0, 0) = 2.0 / anU;
67   aProjMatrix.ChangeValue (1, 0) = 0.0;
68   aProjMatrix.ChangeValue (2, 0) = 0.0;
69   aProjMatrix.ChangeValue (3, 0) = 0.0;
70
71   aProjMatrix.ChangeValue (0, 1) = 0.0;
72   aProjMatrix.ChangeValue (1, 1) = 2.0 / aV;
73   aProjMatrix.ChangeValue (2, 1) = 0.0;
74   aProjMatrix.ChangeValue (3, 1) = 0.0;
75
76   aProjMatrix.ChangeValue (0, 2) = 0.0;
77   aProjMatrix.ChangeValue (1, 2) = 0.0;
78   aProjMatrix.ChangeValue (2, 2) = -2.0 * 0.01;
79   aProjMatrix.ChangeValue (3, 2) = 0.0;
80
81   aProjMatrix.ChangeValue (0, 3) = 0.0;
82   aProjMatrix.ChangeValue (1, 3) = 0.0;
83   aProjMatrix.ChangeValue (2, 3) = 0.0;
84   aProjMatrix.ChangeValue (3, 3) = 1.0;
85
86   // Define trihedron position in the view
87   switch (myPos)
88   {
89     case Aspect_TOTP_LEFT_LOWER:
90     {
91       Graphic3d_TransformUtils::Translate (aProjMatrix,
92         -0.5 * anU + myScale, -0.5 * aV + myScale, 0.0);
93       break;
94     }
95     case Aspect_TOTP_LEFT_UPPER:
96     {
97       Graphic3d_TransformUtils::Translate (aProjMatrix,
98         -0.5 * anU + myScale, 0.5 * aV - myScale - myScale / 3.0, 0.0);
99       break;
100     }
101     case Aspect_TOTP_RIGHT_LOWER:
102     {
103       Graphic3d_TransformUtils::Translate (aProjMatrix,
104         0.5 * anU - myScale - myScale / 3.0, -0.5 * aV + myScale, 0.0);
105       break;
106     }
107     case Aspect_TOTP_RIGHT_UPPER:
108     {
109       Graphic3d_TransformUtils::Translate (aProjMatrix,
110         0.5 * anU - myScale - myScale / 3.0, 0.5 * aV - myScale - myScale / 3.0, 0.0);
111       break;
112     }
113     //case Aspect_TOTP_CENTER:
114     default:
115       break;
116   }
117
118   aContext->ProjectionState.SetCurrent<Standard_Real> (aProjMatrix);
119   aContext->ApplyProjectionMatrix();
120
121   aContext->WorldViewState.SetCurrent<Standard_Real> (aModelMatrix);
122   aContext->ApplyWorldViewMatrix();
123 }
124
125 // =======================================================================
126 // function : redraw
127 // purpose  :
128 // =======================================================================
129 void OpenGl_Trihedron::redraw (const Handle(OpenGl_Workspace)& theWorkspace) const
130 {
131   const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
132   aContext->WorldViewState.Push();
133   aContext->ProjectionState.Push();
134
135   resetTransformations (theWorkspace);
136
137   // Set trihedron size parameters
138   GLdouble aScale = myScale;
139   aScale *= myRatio;
140   const Standard_Real aLineRatio = 0.75;
141   const GLdouble aLineLength = aScale * aLineRatio;
142   const GLdouble aConeDiametr     = aScale * myDiameter;
143   const GLdouble aConeLength      = aScale * (1.0 - aLineRatio);
144   const GLdouble aRayon = aScale / 30.0;
145
146   // Create primitive line here for changing length
147   if (!myLine.IsInitialized())
148   {
149     Handle(Graphic3d_ArrayOfSegments) aGraphicArray = new Graphic3d_ArrayOfSegments (2);
150     aGraphicArray->AddVertex (0.0, 0.0, 0.0);
151     aGraphicArray->AddVertex (0.0, 0.0, aLineLength);
152     myLine.InitBuffers (aContext, Graphic3d_TOPA_SEGMENTS, aGraphicArray->Indices(),
153                         aGraphicArray->Attributes(),
154                         aGraphicArray->Bounds());
155   }
156
157   if (!myCircle.IsInitialized())
158   {
159     const Standard_Integer THE_CIRCLE_SERMENTS_NB = 24;
160     Handle(Graphic3d_ArrayOfPolylines) anCircleArray = new Graphic3d_ArrayOfPolylines (THE_CIRCLE_SERMENTS_NB + 2);
161
162     const Standard_Real THE_CIRCLE_SEGMENT_ANGLE = 2.0 * M_PI / THE_CIRCLE_SERMENTS_NB;
163     for (Standard_Integer anIt = THE_CIRCLE_SERMENTS_NB; anIt >= 0; --anIt)
164     {
165       anCircleArray->AddVertex (aRayon * sin (anIt * THE_CIRCLE_SEGMENT_ANGLE),
166                                 aRayon * cos (anIt * THE_CIRCLE_SEGMENT_ANGLE), 0.0);
167     }
168     anCircleArray->AddVertex (aRayon * sin (THE_CIRCLE_SERMENTS_NB * THE_CIRCLE_SEGMENT_ANGLE),
169                               aRayon * cos (THE_CIRCLE_SERMENTS_NB * THE_CIRCLE_SEGMENT_ANGLE), 0.0);
170
171     myCircle.InitBuffers (aContext, Graphic3d_TOPA_POLYLINES, anCircleArray->Indices(),
172                           anCircleArray->Attributes(), anCircleArray->Bounds());
173   }
174
175   if (!myDisk.IsInitialized())
176   {
177     myDisk.Init (0.0, static_cast<GLfloat> (aConeDiametr), myNbFacettes, 1);
178   }
179
180   if (!myCone.IsInitialized())
181   {
182     myCone.Init (static_cast<GLfloat> (aConeDiametr), 0.0f, static_cast<GLfloat> (aConeLength), myNbFacettes, 1);
183   }
184
185   OpenGl_AspectFace anAspectX;
186   OpenGl_AspectFace anAspectY;
187   OpenGl_AspectFace anAspectZ;
188   OpenGl_AspectLine anAspectLine;
189   memcpy (anAspectX.ChangeIntFront().matcol.rgb, myXColor.GetData(), sizeof (TEL_COLOUR));
190   memcpy (anAspectY.ChangeIntFront().matcol.rgb, myYColor.GetData(), sizeof (TEL_COLOUR));
191   memcpy (anAspectZ.ChangeIntFront().matcol.rgb, myZColor.GetData(), sizeof (TEL_COLOUR));
192   OpenGl_Mat4d aModelMatrix;
193   aModelMatrix.Convert (aContext->WorldViewState.Current());
194   OpenGl_Mat4d aModelViewX (aModelMatrix);
195   OpenGl_Mat4d aModelViewY (aModelMatrix);
196   OpenGl_Mat4d aModelViewZ (aModelMatrix);
197
198   // Set line aspect
199   const OpenGl_AspectLine* aCurrentAspectLine = theWorkspace->AspectLine (Standard_True);
200   CALL_DEF_CONTEXTLINE aLineAspect = {1, 1, { 1.F, 1.F, 1.F },  aCurrentAspectLine->Type(), aCurrentAspectLine->Width()};
201   aLineAspect.Color.r = myZColor.r();
202   aLineAspect.Color.g = myZColor.g();
203   aLineAspect.Color.b = myZColor.b();
204   anAspectLine.SetAspect (aLineAspect);
205
206   // Disable depth test and face culling
207   GLboolean wasDepthMaskEnabled = GL_FALSE;
208   GLint aDepthFuncBack = 0, aCullFaceModeBack = GL_BACK;
209   const GLboolean wasDepthEnabled    = aContext->core11fwd->glIsEnabled (GL_DEPTH_TEST);
210   const GLboolean wasCullFaceEnabled = aContext->core11fwd->glIsEnabled (GL_CULL_FACE);
211   aContext->core11fwd->glGetIntegerv (GL_DEPTH_FUNC,      &aDepthFuncBack);
212   aContext->core11fwd->glGetIntegerv (GL_CULL_FACE_MODE,  &aCullFaceModeBack);
213   aContext->core11fwd->glGetBooleanv (GL_DEPTH_WRITEMASK, &wasDepthMaskEnabled);
214   if (!wasDepthEnabled)
215   {
216     aContext->core11fwd->glEnable (GL_DEPTH_TEST);
217     aContext->core11fwd->glClear (GL_DEPTH_BUFFER_BIT);
218   }
219   if (!wasDepthMaskEnabled)
220   {
221     aContext->core11fwd->glDepthMask (GL_TRUE);
222   }
223   aContext->core11fwd->glCullFace (GL_BACK);
224   if (!wasCullFaceEnabled)
225   {
226     aContext->core11fwd->glEnable (GL_CULL_FACE);
227   }
228
229   // Origin
230   myCircle.Render (theWorkspace);
231
232   // Z axis
233   const OpenGl_AspectFace* anOldAspectFace = theWorkspace->SetAspectFace(&anAspectZ);
234   theWorkspace->SetAspectLine (&anAspectLine);
235   myLine.Render (theWorkspace);
236   Graphic3d_TransformUtils::Translate (aModelViewZ, 0.0, 0.0, aLineLength);
237   aContext->WorldViewState.SetCurrent<Standard_Real>(aModelViewZ);
238   aContext->ApplyWorldViewMatrix();
239   myDisk.Render (theWorkspace);
240   myCone.Render (theWorkspace);
241
242   // X axis
243   theWorkspace->SetAspectFace (&anAspectX);
244   Graphic3d_TransformUtils::Rotate (aModelViewX, 90.0, 0.0, aScale, 0.0);
245   aContext->WorldViewState.SetCurrent<Standard_Real> (aModelViewX);
246   aContext->ApplyWorldViewMatrix();
247
248   aLineAspect.Color.r = myXColor.r();
249   aLineAspect.Color.g = myXColor.g();
250   aLineAspect.Color.b = myXColor.b();
251   anAspectLine.SetAspect (aLineAspect);
252   theWorkspace->SetAspectLine (&anAspectLine);
253   myLine.Render (theWorkspace);
254   Graphic3d_TransformUtils::Translate (aModelViewX, 0.0, 0.0, aLineLength);
255   aContext->WorldViewState.SetCurrent<Standard_Real> (aModelViewX);
256   aContext->ApplyWorldViewMatrix();
257   myDisk.Render (theWorkspace);
258   myCone.Render (theWorkspace);
259
260   // Y axis
261   theWorkspace->SetAspectFace (&anAspectY);
262   Graphic3d_TransformUtils::Rotate (aModelViewY, -90.0, aScale, 0.0, 0.0);
263   aContext->WorldViewState.SetCurrent<Standard_Real> (aModelViewY);
264   aContext->ApplyWorldViewMatrix();
265
266   aLineAspect.Color.r = myYColor.r();
267   aLineAspect.Color.g = myYColor.g();
268   aLineAspect.Color.b = myYColor.b();
269   anAspectLine.SetAspect (aLineAspect);
270   theWorkspace->SetAspectLine (&anAspectLine);
271   myLine.Render (theWorkspace);
272   Graphic3d_TransformUtils::Translate (aModelViewY, 0.0, 0.0, aLineLength);
273   aContext->WorldViewState.SetCurrent<Standard_Real> (aModelViewY);
274   aContext->ApplyWorldViewMatrix();
275   myDisk.Render (theWorkspace);
276   myCone.Render (theWorkspace);
277
278   // Restore aspects
279   theWorkspace->SetAspectFace (anOldAspectFace);
280
281   if (!wasDepthEnabled)
282   {
283     aContext->core11fwd->glDisable (GL_DEPTH_TEST);
284   }
285   if (!wasDepthMaskEnabled)
286   {
287     aContext->core11fwd->glDepthMask (GL_FALSE);
288   }
289   if (!wasCullFaceEnabled)
290   {
291     aContext->core11fwd->glDisable (GL_CULL_FACE);
292   }
293   aContext->core11fwd->glCullFace (aCullFaceModeBack);
294
295   // Always write the text
296   aContext->core11fwd->glDepthFunc (GL_ALWAYS);
297
298   // Render labels
299   myLabelX.SetPosition (OpenGl_Vec3 (float (aScale + 2.0 * aRayon), 0.0f, float (-aRayon)));
300   myLabelY.SetPosition (OpenGl_Vec3 (float (aRayon), float (aScale + 3.0 * aRayon), float (2.0 * aRayon)));
301   myLabelZ.SetPosition (OpenGl_Vec3 (float (-2.0 * aRayon), float (0.5 * aRayon), float (aScale + 3.0 * aRayon)));
302   aContext->WorldViewState.SetCurrent<Standard_Real> (aModelMatrix);
303   aContext->ApplyWorldViewMatrix();
304   myLabelX.Render (theWorkspace);
305   myLabelY.Render (theWorkspace);
306   myLabelZ.Render (theWorkspace);
307
308   aContext->core11fwd->glDepthFunc (aDepthFuncBack);
309   aContext->WorldViewState.Pop();
310   aContext->ProjectionState.Pop();
311   aContext->ApplyProjectionMatrix();
312 }
313
314 // =======================================================================
315 // function : redrawZBuffer
316 // purpose  :
317 // =======================================================================
318 void OpenGl_Trihedron::redrawZBuffer (const Handle(OpenGl_Workspace)& theWorkspace) const
319 {
320   Handle(OpenGl_Context) aContext = theWorkspace->GetGlContext();
321   aContext->WorldViewState.Push();
322   aContext->ProjectionState.Push();
323
324   resetTransformations (theWorkspace);
325
326   const GLdouble aScale = myScale * myRatio;
327
328   const OpenGl_AspectLine* anAspectLine = theWorkspace->AspectLine (Standard_True);
329   const TEL_COLOUR&        aLineColor   = anAspectLine->Color();
330
331   // Create the trihedron
332   const Standard_Real THE_CYLINDER_LENGTH = 0.75;
333   const GLdouble aCylinderLength  = aScale * THE_CYLINDER_LENGTH;
334   const GLdouble aCylinderDiametr = aScale * myDiameter;
335   const GLdouble aConeDiametr     = aCylinderDiametr * 2.0;
336   const GLdouble aConeLength      = aScale * (1.0 - THE_CYLINDER_LENGTH);
337
338   // Position des Axes
339   GLdouble aTriedronAxeX[3] = { aScale, 0.0,    0.0 };
340   GLdouble aTriedronAxeY[3] = { 0.0,    aScale, 0.0 };
341   if (!myDisk.IsInitialized())
342   {
343     myDisk.Init (static_cast<GLfloat> (aCylinderDiametr),
344                  static_cast<GLfloat> (aConeDiametr),
345                  myNbFacettes, 1);
346   }
347
348   if (!mySphere.IsInitialized())
349   {
350     mySphere.Init (static_cast<GLfloat> (aCylinderDiametr * 2.0), myNbFacettes, myNbFacettes);
351   }
352
353   if (!myCone.IsInitialized())
354   {
355     myCone.Init (static_cast<GLfloat> (aConeDiametr), 0.0f, static_cast<GLfloat> (aConeLength), myNbFacettes, 1);
356   }
357
358   if (!myCylinder.IsInitialized())
359   {
360     myCylinder.Init (static_cast<GLfloat> (aCylinderDiametr),
361                      static_cast<GLfloat> (aCylinderDiametr),
362                      static_cast<GLfloat> (aCylinderLength),
363                      myNbFacettes, 1);
364   }
365
366   GLboolean wasDepthMaskEnabled = GL_FALSE;
367   GLint aDepthFuncBack = 0, aCullFaceModeBack = GL_BACK;
368   const GLboolean wasDepthEnabled    = aContext->core11fwd->glIsEnabled (GL_DEPTH_TEST);
369   const GLboolean wasCullFaceEnabled = aContext->core11fwd->glIsEnabled (GL_CULL_FACE);
370   aContext->core11fwd->glGetIntegerv (GL_DEPTH_FUNC,      &aDepthFuncBack);
371   aContext->core11fwd->glGetIntegerv (GL_CULL_FACE_MODE,  &aCullFaceModeBack);
372   aContext->core11fwd->glGetBooleanv (GL_DEPTH_WRITEMASK, &wasDepthMaskEnabled);
373   if (!wasDepthEnabled)
374   {
375     aContext->core11fwd->glEnable (GL_DEPTH_TEST);
376     aContext->core11fwd->glClear (GL_DEPTH_BUFFER_BIT);
377   }
378   if (!wasDepthMaskEnabled)
379   {
380     aContext->core11fwd->glDepthMask (GL_TRUE);
381   }
382   aContext->core11fwd->glCullFace (GL_BACK);
383   if (!wasCullFaceEnabled)
384   {
385     aContext->core11fwd->glEnable (GL_CULL_FACE);
386   }
387
388   OpenGl_AspectFace anAspectC;
389   OpenGl_AspectFace anAspectX;
390   OpenGl_AspectFace anAspectY;
391   OpenGl_AspectFace anAspectZ;
392   memcpy (anAspectX.ChangeIntFront().matcol.rgb, myXColor.GetData(), sizeof (TEL_COLOUR));
393   memcpy (anAspectY.ChangeIntFront().matcol.rgb, myYColor.GetData(), sizeof (TEL_COLOUR));
394   memcpy (anAspectZ.ChangeIntFront().matcol.rgb, myZColor.GetData(), sizeof (TEL_COLOUR));
395   memcpy (anAspectC.ChangeIntFront().matcol.rgb, aLineColor.rgb,     sizeof (TEL_COLOUR));
396
397   OpenGl_Mat4d aModelMatrix;
398   aModelMatrix.Convert (aContext->WorldViewState.Current());
399   for (Standard_Integer aPass = 0; aPass < 2; ++aPass)
400   {
401     OpenGl_Mat4d aModelViewX (aModelMatrix);
402     OpenGl_Mat4d aModelViewY (aModelMatrix);
403     OpenGl_Mat4d aModelViewZ (aModelMatrix);
404     aContext->core11fwd->glDepthFunc (aPass == 0 ? GL_ALWAYS : GL_LEQUAL);
405
406     const OpenGl_AspectFace* anOldAspect = theWorkspace->SetAspectFace (&anAspectC);
407
408     // Origin
409     aContext->WorldViewState.SetCurrent<Standard_Real> (aModelMatrix);
410     aContext->ApplyWorldViewMatrix();
411     mySphere.Render (theWorkspace);
412
413     // Z axis
414     theWorkspace->SetAspectFace (&anAspectZ);
415     myCylinder.Render (theWorkspace);
416     Graphic3d_TransformUtils::Translate (aModelViewZ, 0.0, 0.0, aScale * THE_CYLINDER_LENGTH);
417     aContext->WorldViewState.SetCurrent<Standard_Real> (aModelViewZ);
418     aContext->ApplyWorldViewMatrix();
419     myDisk.Render (theWorkspace);
420     myCone.Render (theWorkspace);
421
422     // X axis
423     theWorkspace->SetAspectFace (&anAspectX);
424     Graphic3d_TransformUtils::Rotate (aModelViewX, 90.0, aTriedronAxeY[0], aTriedronAxeY[1], aTriedronAxeY[2]);
425     aContext->WorldViewState.SetCurrent<Standard_Real> (aModelViewX);
426     aContext->ApplyWorldViewMatrix();
427     myCylinder.Render (theWorkspace);
428     Graphic3d_TransformUtils::Translate (aModelViewX, 0.0, 0.0, aScale * THE_CYLINDER_LENGTH);
429     aContext->WorldViewState.SetCurrent<Standard_Real> (aModelViewX);
430     aContext->ApplyWorldViewMatrix();
431     myDisk.Render (theWorkspace);
432     myCone.Render (theWorkspace);
433
434     // Y axis
435     theWorkspace->SetAspectFace (&anAspectY);
436     Graphic3d_TransformUtils::Rotate (aModelViewY, -90.0, aTriedronAxeX[0], aTriedronAxeX[1], aTriedronAxeX[2]);
437     aContext->WorldViewState.SetCurrent<Standard_Real> (aModelViewY);
438     aContext->ApplyWorldViewMatrix();
439     myCylinder.Render (theWorkspace);
440     Graphic3d_TransformUtils::Translate (aModelViewY, 0.0, 0.0, aScale * THE_CYLINDER_LENGTH);
441     aContext->WorldViewState.SetCurrent<Standard_Real> (aModelViewY);
442     aContext->ApplyWorldViewMatrix();
443     myDisk.Render (theWorkspace);
444     myCone.Render (theWorkspace);
445
446     theWorkspace->SetAspectFace (anOldAspect);
447   }
448
449   if (!wasDepthEnabled)
450   {
451     aContext->core11fwd->glDisable (GL_DEPTH_TEST);
452   }
453   if (!wasDepthMaskEnabled)
454   {
455     aContext->core11fwd->glDepthMask (GL_FALSE);
456   }
457   if (!wasCullFaceEnabled)
458   {
459     aContext->core11fwd->glDisable (GL_CULL_FACE);
460   }
461   aContext->core11fwd->glCullFace (aCullFaceModeBack);
462
463   // Always write the text
464   aContext->core11fwd->glDepthFunc (GL_ALWAYS);
465
466   // draw axes labels
467   const GLdouble rayon = aScale / 30.0;
468   myLabelX.SetPosition (OpenGl_Vec3(float(aScale + 2.0 * rayon), 0.0f,                        float(-rayon)));
469   myLabelY.SetPosition (OpenGl_Vec3(float(rayon),                float(aScale + 3.0 * rayon), float(2.0 * rayon)));
470   myLabelZ.SetPosition (OpenGl_Vec3(float(-2.0 * rayon),         float(0.5 * rayon),          float(aScale + 3.0 * rayon)));
471   aContext->WorldViewState.SetCurrent<Standard_Real> (aModelMatrix);
472   aContext->ApplyWorldViewMatrix();
473   myLabelX.Render (theWorkspace);
474   myLabelY.Render (theWorkspace);
475   myLabelZ.Render (theWorkspace);
476
477   aContext->core11fwd->glDepthFunc (aDepthFuncBack);
478
479   aContext->WorldViewState.Pop();
480   aContext->ProjectionState.Pop();
481   aContext->ApplyProjectionMatrix();
482 }
483
484 // =======================================================================
485 // function : OpenGl_Trihedron
486 // purpose  :
487 // =======================================================================
488 OpenGl_Trihedron::OpenGl_Trihedron()
489 : myPos (Aspect_TOTP_LEFT_LOWER),
490   myScale (1.0),
491   myIsWireframe (Standard_False),
492   myXColor (1.0f, 0.0f, 0.0f, 0.6f),
493   myYColor (0.0f, 1.0f, 0.0f, 0.6f),
494   myZColor (0.0f, 0.0f, 1.0f, 0.6f),
495   myRatio      (0.8f),
496   myDiameter   (0.05f),
497   myNbFacettes (12),
498   myLabelX ("X", OpenGl_Vec3(1.0f, 0.0f, 0.0f), THE_LABEL_PARAMS),
499   myLabelY ("Y", OpenGl_Vec3(0.0f, 1.0f, 0.0f), THE_LABEL_PARAMS),
500   myLabelZ ("Z", OpenGl_Vec3(0.0f, 0.0f, 1.0f), THE_LABEL_PARAMS),
501   myLine   (NULL), // do not register arrays UID - trihedron is not intended to be drawn by Ray Tracing engine
502   myCircle (NULL)
503 {
504   const TEL_COLOUR aWhiteColor = {{ 1.0f, 1.0f, 1.0f, 1.0f }};
505   myAspectLine.ChangeColor()    = aWhiteColor;
506   myAspectText.ChangeColor()    = aWhiteColor;
507   myAspectText.ChangeFontName() = "Courier";
508 }
509
510 // =======================================================================
511 // function : ~OpenGl_Trihedron
512 // purpose  :
513 // =======================================================================
514 OpenGl_Trihedron::~OpenGl_Trihedron()
515 {
516   //
517 }
518
519 // =======================================================================
520 // function : Release
521 // purpose  :
522 // =======================================================================
523 void OpenGl_Trihedron::Release (OpenGl_Context* theCtx)
524 {
525   myLabelX.Release (theCtx);
526   myLabelY.Release (theCtx);
527   myLabelZ.Release (theCtx);
528   myAspectLine.Release (theCtx);
529   myAspectText.Release (theCtx);
530   myCone    .Release (theCtx);
531   myDisk    .Release (theCtx);
532   mySphere  .Release (theCtx);
533   myCylinder.Release (theCtx);
534   myLine.Release (theCtx);
535   myCircle.Release (theCtx);
536 }
537
538 // =======================================================================
539 // function : invalidate
540 // purpose  :
541 // =======================================================================
542 void OpenGl_Trihedron::invalidate()
543 {
544   myCone    .Invalidate();
545   myDisk    .Invalidate();
546   mySphere  .Invalidate();
547   myCylinder.Invalidate();
548   myLine    .Invalidate();
549   myCircle  .Invalidate();
550 }
551
552 // =======================================================================
553 // function : SetScale
554 // purpose  :
555 // =======================================================================
556 void OpenGl_Trihedron::SetScale (const Standard_Real theScale)
557 {
558   if (Abs (myScale - theScale) > Precision::Confusion())
559   {
560     invalidate();
561   }
562   myScale = theScale;
563 }
564
565 // =======================================================================
566 // function : SetSizeRatio
567 // purpose  :
568 // =======================================================================
569 void OpenGl_Trihedron::SetSizeRatio (const Standard_Real theRatio)
570 {
571   if (Abs (Standard_Real(myRatio) - theRatio) > Precision::Confusion())
572   {
573     invalidate();
574   }
575   myRatio = float(theRatio);
576 }
577
578 // =======================================================================
579 // function : SetArrowDiameter
580 // purpose  :
581 // =======================================================================
582 void OpenGl_Trihedron::SetArrowDiameter (const Standard_Real theDiam)
583 {
584   if (Abs (Standard_Real(myDiameter) - theDiam) > Precision::Confusion())
585   {
586     invalidate();
587   }
588   myDiameter = float(theDiam);
589 }
590
591 // =======================================================================
592 // function : SetNbFacets
593 // purpose  :
594 // =======================================================================
595 void OpenGl_Trihedron::SetNbFacets (const Standard_Integer theNbFacets)
596 {
597   if (Abs (myNbFacettes - theNbFacets) > 0)
598   {
599     invalidate();
600   }
601   myNbFacettes = theNbFacets;
602 }
603
604 // =======================================================================
605 // function : SetLabelsColor
606 // purpose  :
607 // =======================================================================
608 void OpenGl_Trihedron::SetLabelsColor (const Quantity_Color& theColor)
609 {
610   myAspectText.ChangeColor().rgb[0] = float(theColor.Red());
611   myAspectText.ChangeColor().rgb[1] = float(theColor.Green());
612   myAspectText.ChangeColor().rgb[2] = float(theColor.Blue());
613 }
614
615 // =======================================================================
616 // function : SetArrowsColors
617 // purpose  :
618 // =======================================================================
619 void OpenGl_Trihedron::SetArrowsColors (const Quantity_Color& theColorX,
620                                         const Quantity_Color& theColorY,
621                                         const Quantity_Color& theColorZ)
622 {
623   myXColor = OpenGl_Vec4 (float(theColorX.Red()), float(theColorX.Green()), float(theColorX.Blue()), 0.6f);
624   myYColor = OpenGl_Vec4 (float(theColorY.Red()), float(theColorY.Green()), float(theColorY.Blue()), 0.6f);
625   myZColor = OpenGl_Vec4 (float(theColorZ.Red()), float(theColorZ.Green()), float(theColorZ.Blue()), 0.6f);
626 }
627
628 // =======================================================================
629 // function : Render
630 // purpose  :
631 // =======================================================================
632 void OpenGl_Trihedron::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
633 {
634   const OpenGl_AspectLine* aPrevAspectLine = theWorkspace->SetAspectLine (&myAspectLine);
635   const OpenGl_AspectText* aPrevAspectText = theWorkspace->SetAspectText (&myAspectText);
636
637   /* check if GL_LIGHTING should be disabled
638   no enabling 'cause it will be done (if necessary: kinda Polygon types )
639   during redrawing structures
640   */
641   if (!theWorkspace->UseGLLight())
642   {
643   #if !defined(GL_ES_VERSION_2_0)
644     glDisable (GL_LIGHTING);
645   #endif
646   }
647
648   const Handle(OpenGl_Texture) aPrevTexture = theWorkspace->DisableTexture();
649
650   theWorkspace->GetGlContext()->ApplyModelViewMatrix();
651
652   if (myIsWireframe)
653   {
654     redraw (theWorkspace);
655   }
656   else
657   {
658     redrawZBuffer (theWorkspace);
659   }
660
661   // restore aspects
662   if (!aPrevTexture.IsNull())
663   {
664     theWorkspace->EnableTexture (aPrevTexture);
665   }
666
667   theWorkspace->SetAspectText (aPrevAspectText);
668   theWorkspace->SetAspectLine (aPrevAspectLine);
669 }