0027670: Visualization - avoid duplication of structures defining primitive array...
[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 Handle(Graphic3d_Camera)& aCamera  = theWorkspace->View()->Camera();
44   double anU = 1.0;
45   double aV  = 1.0;
46   if (aCamera->ViewDimensions().X() < aCamera->ViewDimensions().Y())
47   {
48     aV  = aCamera->ViewDimensions().Y() / aCamera->ViewDimensions().X();
49   }
50   else
51   {
52     anU = aCamera->ViewDimensions().X() / aCamera->ViewDimensions().Y();
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   anAspectX.Aspect()->SetInteriorColor (Quantity_Color (myXColor.rgb()));
190   anAspectY.Aspect()->SetInteriorColor (Quantity_Color (myYColor.rgb()));
191   anAspectZ.Aspect()->SetInteriorColor (Quantity_Color (myZColor.rgb()));
192
193   OpenGl_Mat4d aModelMatrix;
194   aModelMatrix.Convert (aContext->WorldViewState.Current());
195   OpenGl_Mat4d aModelViewX (aModelMatrix);
196   OpenGl_Mat4d aModelViewY (aModelMatrix);
197   OpenGl_Mat4d aModelViewZ (aModelMatrix);
198
199   // Set line aspect
200   const OpenGl_AspectLine* aCurrentAspectLine = theWorkspace->ApplyAspectLine();
201   Handle(Graphic3d_AspectLine3d) anAspectLine3d = new Graphic3d_AspectLine3d (Quantity_Color(), aCurrentAspectLine->Aspect()->Type(), aCurrentAspectLine->Aspect()->Width());
202   anAspectLine.SetAspect (anAspectLine3d);
203
204   // Disable depth test and face culling
205   GLboolean wasDepthMaskEnabled = GL_FALSE;
206   GLint aDepthFuncBack = 0, aCullFaceModeBack = GL_BACK;
207   const GLboolean wasDepthEnabled    = aContext->core11fwd->glIsEnabled (GL_DEPTH_TEST);
208   const GLboolean wasCullFaceEnabled = aContext->core11fwd->glIsEnabled (GL_CULL_FACE);
209   aContext->core11fwd->glGetIntegerv (GL_DEPTH_FUNC,      &aDepthFuncBack);
210   aContext->core11fwd->glGetIntegerv (GL_CULL_FACE_MODE,  &aCullFaceModeBack);
211   aContext->core11fwd->glGetBooleanv (GL_DEPTH_WRITEMASK, &wasDepthMaskEnabled);
212   if (!wasDepthEnabled)
213   {
214     aContext->core11fwd->glEnable (GL_DEPTH_TEST);
215     aContext->core11fwd->glClear (GL_DEPTH_BUFFER_BIT);
216   }
217   if (!wasDepthMaskEnabled)
218   {
219     aContext->core11fwd->glDepthMask (GL_TRUE);
220   }
221   aContext->core11fwd->glCullFace (GL_BACK);
222   if (!wasCullFaceEnabled)
223   {
224     aContext->core11fwd->glEnable (GL_CULL_FACE);
225   }
226
227   // Origin
228   myCircle.Render (theWorkspace);
229
230   // Z axis
231   const OpenGl_AspectFace* anOldAspectFace = theWorkspace->SetAspectFace(&anAspectZ);
232   anAspectLine3d->SetColor (Quantity_Color (myZColor.rgb()));
233   theWorkspace->SetAspectLine (&anAspectLine);
234   myLine.Render (theWorkspace);
235   Graphic3d_TransformUtils::Translate (aModelViewZ, 0.0, 0.0, aLineLength);
236   aContext->WorldViewState.SetCurrent<Standard_Real>(aModelViewZ);
237   aContext->ApplyWorldViewMatrix();
238   myDisk.Render (theWorkspace);
239   myCone.Render (theWorkspace);
240
241   // X axis
242   theWorkspace->SetAspectFace (&anAspectX);
243   Graphic3d_TransformUtils::Rotate (aModelViewX, 90.0, 0.0, aScale, 0.0);
244   aContext->WorldViewState.SetCurrent<Standard_Real> (aModelViewX);
245   aContext->ApplyWorldViewMatrix();
246
247   anAspectLine3d->SetColor (Quantity_Color (myXColor.rgb()));
248   theWorkspace->SetAspectLine (&anAspectLine);
249   myLine.Render (theWorkspace);
250   Graphic3d_TransformUtils::Translate (aModelViewX, 0.0, 0.0, aLineLength);
251   aContext->WorldViewState.SetCurrent<Standard_Real> (aModelViewX);
252   aContext->ApplyWorldViewMatrix();
253   myDisk.Render (theWorkspace);
254   myCone.Render (theWorkspace);
255
256   // Y axis
257   theWorkspace->SetAspectFace (&anAspectY);
258   Graphic3d_TransformUtils::Rotate (aModelViewY, -90.0, aScale, 0.0, 0.0);
259   aContext->WorldViewState.SetCurrent<Standard_Real> (aModelViewY);
260   aContext->ApplyWorldViewMatrix();
261
262   anAspectLine3d->SetColor (Quantity_Color (myYColor.rgb()));
263   theWorkspace->SetAspectLine (&anAspectLine);
264   myLine.Render (theWorkspace);
265   Graphic3d_TransformUtils::Translate (aModelViewY, 0.0, 0.0, aLineLength);
266   aContext->WorldViewState.SetCurrent<Standard_Real> (aModelViewY);
267   aContext->ApplyWorldViewMatrix();
268   myDisk.Render (theWorkspace);
269   myCone.Render (theWorkspace);
270
271   // Restore aspects
272   theWorkspace->SetAspectFace (anOldAspectFace);
273
274   if (!wasDepthEnabled)
275   {
276     aContext->core11fwd->glDisable (GL_DEPTH_TEST);
277   }
278   if (!wasDepthMaskEnabled)
279   {
280     aContext->core11fwd->glDepthMask (GL_FALSE);
281   }
282   if (!wasCullFaceEnabled)
283   {
284     aContext->core11fwd->glDisable (GL_CULL_FACE);
285   }
286   aContext->core11fwd->glCullFace (aCullFaceModeBack);
287
288   // Always write the text
289   aContext->core11fwd->glDepthFunc (GL_ALWAYS);
290
291   // Render labels
292   myLabelX.SetPosition (OpenGl_Vec3 (float (aScale + 2.0 * aRayon), 0.0f, float (-aRayon)));
293   myLabelY.SetPosition (OpenGl_Vec3 (float (aRayon), float (aScale + 3.0 * aRayon), float (2.0 * aRayon)));
294   myLabelZ.SetPosition (OpenGl_Vec3 (float (-2.0 * aRayon), float (0.5 * aRayon), float (aScale + 3.0 * aRayon)));
295   aContext->WorldViewState.SetCurrent<Standard_Real> (aModelMatrix);
296   aContext->ApplyWorldViewMatrix();
297   myLabelX.Render (theWorkspace);
298   myLabelY.Render (theWorkspace);
299   myLabelZ.Render (theWorkspace);
300
301   aContext->core11fwd->glDepthFunc (aDepthFuncBack);
302   aContext->WorldViewState.Pop();
303   aContext->ProjectionState.Pop();
304   aContext->ApplyProjectionMatrix();
305 }
306
307 // =======================================================================
308 // function : redrawZBuffer
309 // purpose  :
310 // =======================================================================
311 void OpenGl_Trihedron::redrawZBuffer (const Handle(OpenGl_Workspace)& theWorkspace) const
312 {
313   Handle(OpenGl_Context) aContext = theWorkspace->GetGlContext();
314   aContext->WorldViewState.Push();
315   aContext->ProjectionState.Push();
316
317   resetTransformations (theWorkspace);
318
319   const GLdouble aScale = myScale * myRatio;
320
321   const OpenGl_AspectLine* anAspectLine = theWorkspace->ApplyAspectLine();
322   const OpenGl_Vec4&       aLineColor   = anAspectLine->Aspect()->ColorRGBA();
323
324   // Create the trihedron
325   const Standard_Real THE_CYLINDER_LENGTH = 0.75;
326   const GLdouble aCylinderLength  = aScale * THE_CYLINDER_LENGTH;
327   const GLdouble aCylinderDiametr = aScale * myDiameter;
328   const GLdouble aConeDiametr     = aCylinderDiametr * 2.0;
329   const GLdouble aConeLength      = aScale * (1.0 - THE_CYLINDER_LENGTH);
330
331   // Position des Axes
332   GLdouble aTriedronAxeX[3] = { aScale, 0.0,    0.0 };
333   GLdouble aTriedronAxeY[3] = { 0.0,    aScale, 0.0 };
334   if (!myDisk.IsInitialized())
335   {
336     myDisk.Init (static_cast<GLfloat> (aCylinderDiametr),
337                  static_cast<GLfloat> (aConeDiametr),
338                  myNbFacettes, 1);
339   }
340
341   if (!mySphere.IsInitialized())
342   {
343     mySphere.Init (static_cast<GLfloat> (aCylinderDiametr * 2.0), myNbFacettes, myNbFacettes);
344   }
345
346   if (!myCone.IsInitialized())
347   {
348     myCone.Init (static_cast<GLfloat> (aConeDiametr), 0.0f, static_cast<GLfloat> (aConeLength), myNbFacettes, 1);
349   }
350
351   if (!myCylinder.IsInitialized())
352   {
353     myCylinder.Init (static_cast<GLfloat> (aCylinderDiametr),
354                      static_cast<GLfloat> (aCylinderDiametr),
355                      static_cast<GLfloat> (aCylinderLength),
356                      myNbFacettes, 1);
357   }
358
359   GLboolean wasDepthMaskEnabled = GL_FALSE;
360   GLint aDepthFuncBack = 0, aCullFaceModeBack = GL_BACK;
361   const GLboolean wasDepthEnabled    = aContext->core11fwd->glIsEnabled (GL_DEPTH_TEST);
362   const GLboolean wasCullFaceEnabled = aContext->core11fwd->glIsEnabled (GL_CULL_FACE);
363   aContext->core11fwd->glGetIntegerv (GL_DEPTH_FUNC,      &aDepthFuncBack);
364   aContext->core11fwd->glGetIntegerv (GL_CULL_FACE_MODE,  &aCullFaceModeBack);
365   aContext->core11fwd->glGetBooleanv (GL_DEPTH_WRITEMASK, &wasDepthMaskEnabled);
366   if (!wasDepthEnabled)
367   {
368     aContext->core11fwd->glEnable (GL_DEPTH_TEST);
369     aContext->core11fwd->glClear (GL_DEPTH_BUFFER_BIT);
370   }
371   if (!wasDepthMaskEnabled)
372   {
373     aContext->core11fwd->glDepthMask (GL_TRUE);
374   }
375   aContext->core11fwd->glCullFace (GL_BACK);
376   if (!wasCullFaceEnabled)
377   {
378     aContext->core11fwd->glEnable (GL_CULL_FACE);
379   }
380
381   OpenGl_AspectFace anAspectC;
382   OpenGl_AspectFace anAspectX;
383   OpenGl_AspectFace anAspectY;
384   OpenGl_AspectFace anAspectZ;
385   anAspectX.Aspect()->SetInteriorColor (Quantity_Color (myXColor.rgb()));
386   anAspectY.Aspect()->SetInteriorColor (Quantity_Color (myYColor.rgb()));
387   anAspectZ.Aspect()->SetInteriorColor (Quantity_Color (myZColor.rgb()));
388   anAspectC.Aspect()->SetInteriorColor (Quantity_Color (aLineColor.rgb()));
389
390   OpenGl_Mat4d aModelMatrix;
391   aModelMatrix.Convert (aContext->WorldViewState.Current());
392   for (Standard_Integer aPass = 0; aPass < 2; ++aPass)
393   {
394     OpenGl_Mat4d aModelViewX (aModelMatrix);
395     OpenGl_Mat4d aModelViewY (aModelMatrix);
396     OpenGl_Mat4d aModelViewZ (aModelMatrix);
397     aContext->core11fwd->glDepthFunc (aPass == 0 ? GL_ALWAYS : GL_LEQUAL);
398
399     const OpenGl_AspectFace* anOldAspect = theWorkspace->SetAspectFace (&anAspectC);
400
401     // Origin
402     aContext->WorldViewState.SetCurrent<Standard_Real> (aModelMatrix);
403     aContext->ApplyWorldViewMatrix();
404     mySphere.Render (theWorkspace);
405
406     // Z axis
407     theWorkspace->SetAspectFace (&anAspectZ);
408     myCylinder.Render (theWorkspace);
409     Graphic3d_TransformUtils::Translate (aModelViewZ, 0.0, 0.0, aScale * THE_CYLINDER_LENGTH);
410     aContext->WorldViewState.SetCurrent<Standard_Real> (aModelViewZ);
411     aContext->ApplyWorldViewMatrix();
412     myDisk.Render (theWorkspace);
413     myCone.Render (theWorkspace);
414
415     // X axis
416     theWorkspace->SetAspectFace (&anAspectX);
417     Graphic3d_TransformUtils::Rotate (aModelViewX, 90.0, aTriedronAxeY[0], aTriedronAxeY[1], aTriedronAxeY[2]);
418     aContext->WorldViewState.SetCurrent<Standard_Real> (aModelViewX);
419     aContext->ApplyWorldViewMatrix();
420     myCylinder.Render (theWorkspace);
421     Graphic3d_TransformUtils::Translate (aModelViewX, 0.0, 0.0, aScale * THE_CYLINDER_LENGTH);
422     aContext->WorldViewState.SetCurrent<Standard_Real> (aModelViewX);
423     aContext->ApplyWorldViewMatrix();
424     myDisk.Render (theWorkspace);
425     myCone.Render (theWorkspace);
426
427     // Y axis
428     theWorkspace->SetAspectFace (&anAspectY);
429     Graphic3d_TransformUtils::Rotate (aModelViewY, -90.0, aTriedronAxeX[0], aTriedronAxeX[1], aTriedronAxeX[2]);
430     aContext->WorldViewState.SetCurrent<Standard_Real> (aModelViewY);
431     aContext->ApplyWorldViewMatrix();
432     myCylinder.Render (theWorkspace);
433     Graphic3d_TransformUtils::Translate (aModelViewY, 0.0, 0.0, aScale * THE_CYLINDER_LENGTH);
434     aContext->WorldViewState.SetCurrent<Standard_Real> (aModelViewY);
435     aContext->ApplyWorldViewMatrix();
436     myDisk.Render (theWorkspace);
437     myCone.Render (theWorkspace);
438
439     theWorkspace->SetAspectFace (anOldAspect);
440   }
441
442   if (!wasDepthEnabled)
443   {
444     aContext->core11fwd->glDisable (GL_DEPTH_TEST);
445   }
446   if (!wasDepthMaskEnabled)
447   {
448     aContext->core11fwd->glDepthMask (GL_FALSE);
449   }
450   if (!wasCullFaceEnabled)
451   {
452     aContext->core11fwd->glDisable (GL_CULL_FACE);
453   }
454   aContext->core11fwd->glCullFace (aCullFaceModeBack);
455
456   // Always write the text
457   aContext->core11fwd->glDepthFunc (GL_ALWAYS);
458
459   // draw axes labels
460   const GLdouble rayon = aScale / 30.0;
461   myLabelX.SetPosition (OpenGl_Vec3(float(aScale + 2.0 * rayon), 0.0f,                        float(-rayon)));
462   myLabelY.SetPosition (OpenGl_Vec3(float(rayon),                float(aScale + 3.0 * rayon), float(2.0 * rayon)));
463   myLabelZ.SetPosition (OpenGl_Vec3(float(-2.0 * rayon),         float(0.5 * rayon),          float(aScale + 3.0 * rayon)));
464   aContext->WorldViewState.SetCurrent<Standard_Real> (aModelMatrix);
465   aContext->ApplyWorldViewMatrix();
466   myLabelX.Render (theWorkspace);
467   myLabelY.Render (theWorkspace);
468   myLabelZ.Render (theWorkspace);
469
470   aContext->core11fwd->glDepthFunc (aDepthFuncBack);
471
472   aContext->WorldViewState.Pop();
473   aContext->ProjectionState.Pop();
474   aContext->ApplyProjectionMatrix();
475 }
476
477 // =======================================================================
478 // function : OpenGl_Trihedron
479 // purpose  :
480 // =======================================================================
481 OpenGl_Trihedron::OpenGl_Trihedron()
482 : myPos (Aspect_TOTP_LEFT_LOWER),
483   myScale (1.0),
484   myIsWireframe (Standard_False),
485   myXColor (1.0f, 0.0f, 0.0f, 0.6f),
486   myYColor (0.0f, 1.0f, 0.0f, 0.6f),
487   myZColor (0.0f, 0.0f, 1.0f, 0.6f),
488   myRatio      (0.8f),
489   myDiameter   (0.05f),
490   myNbFacettes (12),
491   myLabelX ("X", OpenGl_Vec3(1.0f, 0.0f, 0.0f), THE_LABEL_PARAMS),
492   myLabelY ("Y", OpenGl_Vec3(0.0f, 1.0f, 0.0f), THE_LABEL_PARAMS),
493   myLabelZ ("Z", OpenGl_Vec3(0.0f, 0.0f, 1.0f), THE_LABEL_PARAMS),
494   myLine   (NULL), // do not register arrays UID - trihedron is not intended to be drawn by Ray Tracing engine
495   myCircle (NULL)
496 {
497   myAspectLine.SetAspect (new Graphic3d_AspectLine3d (Quantity_NOC_WHITE, Aspect_TOL_SOLID, 1.0));
498   myAspectText.Aspect()->SetColor (Quantity_NOC_WHITE);
499   myAspectText.Aspect()->SetFont ("Courier");
500 }
501
502 // =======================================================================
503 // function : ~OpenGl_Trihedron
504 // purpose  :
505 // =======================================================================
506 OpenGl_Trihedron::~OpenGl_Trihedron()
507 {
508   //
509 }
510
511 // =======================================================================
512 // function : Release
513 // purpose  :
514 // =======================================================================
515 void OpenGl_Trihedron::Release (OpenGl_Context* theCtx)
516 {
517   myLabelX.Release (theCtx);
518   myLabelY.Release (theCtx);
519   myLabelZ.Release (theCtx);
520   myAspectLine.Release (theCtx);
521   myAspectText.Release (theCtx);
522   myCone    .Release (theCtx);
523   myDisk    .Release (theCtx);
524   mySphere  .Release (theCtx);
525   myCylinder.Release (theCtx);
526   myLine.Release (theCtx);
527   myCircle.Release (theCtx);
528 }
529
530 // =======================================================================
531 // function : invalidate
532 // purpose  :
533 // =======================================================================
534 void OpenGl_Trihedron::invalidate()
535 {
536   myCone    .Invalidate();
537   myDisk    .Invalidate();
538   mySphere  .Invalidate();
539   myCylinder.Invalidate();
540   myLine    .Invalidate();
541   myCircle  .Invalidate();
542 }
543
544 // =======================================================================
545 // function : SetScale
546 // purpose  :
547 // =======================================================================
548 void OpenGl_Trihedron::SetScale (const Standard_Real theScale)
549 {
550   if (Abs (myScale - theScale) > Precision::Confusion())
551   {
552     invalidate();
553   }
554   myScale = theScale;
555 }
556
557 // =======================================================================
558 // function : SetSizeRatio
559 // purpose  :
560 // =======================================================================
561 void OpenGl_Trihedron::SetSizeRatio (const Standard_Real theRatio)
562 {
563   if (Abs (Standard_Real(myRatio) - theRatio) > Precision::Confusion())
564   {
565     invalidate();
566   }
567   myRatio = float(theRatio);
568 }
569
570 // =======================================================================
571 // function : SetArrowDiameter
572 // purpose  :
573 // =======================================================================
574 void OpenGl_Trihedron::SetArrowDiameter (const Standard_Real theDiam)
575 {
576   if (Abs (Standard_Real(myDiameter) - theDiam) > Precision::Confusion())
577   {
578     invalidate();
579   }
580   myDiameter = float(theDiam);
581 }
582
583 // =======================================================================
584 // function : SetNbFacets
585 // purpose  :
586 // =======================================================================
587 void OpenGl_Trihedron::SetNbFacets (const Standard_Integer theNbFacets)
588 {
589   if (Abs (myNbFacettes - theNbFacets) > 0)
590   {
591     invalidate();
592   }
593   myNbFacettes = theNbFacets;
594 }
595
596 // =======================================================================
597 // function : SetLabelsColor
598 // purpose  :
599 // =======================================================================
600 void OpenGl_Trihedron::SetLabelsColor (const Quantity_Color& theColor)
601 {
602   myAspectText.Aspect()->SetColor (theColor);
603 }
604
605 // =======================================================================
606 // function : SetArrowsColors
607 // purpose  :
608 // =======================================================================
609 void OpenGl_Trihedron::SetArrowsColors (const Quantity_Color& theColorX,
610                                         const Quantity_Color& theColorY,
611                                         const Quantity_Color& theColorZ)
612 {
613   myXColor = OpenGl_Vec4 (float(theColorX.Red()), float(theColorX.Green()), float(theColorX.Blue()), 0.6f);
614   myYColor = OpenGl_Vec4 (float(theColorY.Red()), float(theColorY.Green()), float(theColorY.Blue()), 0.6f);
615   myZColor = OpenGl_Vec4 (float(theColorZ.Red()), float(theColorZ.Green()), float(theColorZ.Blue()), 0.6f);
616 }
617
618 // =======================================================================
619 // function : Render
620 // purpose  :
621 // =======================================================================
622 void OpenGl_Trihedron::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
623 {
624   const OpenGl_AspectLine* aPrevAspectLine = theWorkspace->SetAspectLine (&myAspectLine);
625   const OpenGl_AspectText* aPrevAspectText = theWorkspace->SetAspectText (&myAspectText);
626
627   /* check if GL_LIGHTING should be disabled
628   no enabling 'cause it will be done (if necessary: kinda Polygon types )
629   during redrawing structures
630   */
631   if (!theWorkspace->UseGLLight())
632   {
633   #if !defined(GL_ES_VERSION_2_0)
634     glDisable (GL_LIGHTING);
635   #endif
636   }
637
638   const Handle(OpenGl_Texture) aPrevTexture = theWorkspace->DisableTexture();
639
640   theWorkspace->GetGlContext()->ApplyModelViewMatrix();
641
642   if (myIsWireframe)
643   {
644     redraw (theWorkspace);
645   }
646   else
647   {
648     redrawZBuffer (theWorkspace);
649   }
650
651   // restore aspects
652   if (!aPrevTexture.IsNull())
653   {
654     theWorkspace->EnableTexture (aPrevTexture);
655   }
656
657   theWorkspace->SetAspectText (aPrevAspectText);
658   theWorkspace->SetAspectLine (aPrevAspectLine);
659 }