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