0025974: Visualization - fix misprints in method naming of Graphic3d_GraduatedTrihedron
[occt.git] / src / OpenGl / OpenGl_GraduatedTrihedron.cxx
1 // Created on: 2011-09-20
2 // Created by: Sergey ZERCHANINOV
3 // Copyright (c) 2011-2013 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_GlCore11.hxx>
17 #include <OpenGl_Utils.hxx>
18 #include <InterfaceGraphic_Graphic3d.hxx>
19 #include <InterfaceGraphic_Aspect.hxx>
20 #include <InterfaceGraphic_Visual3d.hxx>
21
22 #ifndef _WIN32
23   #include <string.h>
24 #endif
25
26 #include <OpenGl_GraduatedTrihedron.hxx>
27
28 #include <Graphic3d_ArrayOfPolylines.hxx>
29 #include <Graphic3d_ArrayOfSegments.hxx>
30 #include <gp_Ax3.hxx>
31 #include <OpenGl_AspectLine.hxx>
32 #include <OpenGl_Utils.hxx>
33 #include <OpenGl_Workspace.hxx>
34 #include <OpenGl_View.hxx>
35 #include <OpenGl_Cylinder.hxx>
36 #include <Precision.hxx>
37
38 namespace
39 {
40   static const OpenGl_TextParam THE_LABEL_PARAMS =
41   {
42     16, Graphic3d_HTA_LEFT, Graphic3d_VTA_BOTTOM
43   };
44 }
45
46 // =======================================================================
47 // function : Constructor
48 // purpose  :
49 // =======================================================================
50 OpenGl_GraduatedTrihedron::OpenGl_GraduatedTrihedron()
51 : myMin (0.0f, 0.0f, 0.0f),
52   myMax (100.0f, 100.0f, 100.0f)
53 {
54   //
55 }
56
57 // =======================================================================
58 // function : SetValues
59 // purpose  :
60 // =======================================================================
61 void OpenGl_GraduatedTrihedron::SetValues (const Handle(OpenGl_Context)&       theCtx,
62                                            const Graphic3d_GraduatedTrihedron& theData)
63 {
64   Release (theCtx.operator->());
65   myData = theData;
66
67   // Initialize text label parameters for x, y, and z axes
68   myAxes[0] = Axis (myData.XAxisAspect(), OpenGl_Vec3 (1.0f, 0.0f, 0.0f));
69   myAxes[1] = Axis (myData.YAxisAspect(), OpenGl_Vec3 (0.0f, 1.0f, 0.0f));
70   myAxes[2] = Axis (myData.ZAxisAspect(), OpenGl_Vec3 (0.0f, 0.0f, 1.0f));
71
72   // Initialize constant primitives: text, arrows.
73   myAxes[0].InitArrow (theCtx, myData.ArrowsLength(), OpenGl_Vec3 (0.0f, 0.0f, 1.0f));
74   myAxes[1].InitArrow (theCtx, myData.ArrowsLength(), OpenGl_Vec3 (0.0f, 0.0f, 1.0f));
75   myAxes[2].InitArrow (theCtx, myData.ArrowsLength(), OpenGl_Vec3 (1.0f, 0.0f, 0.0f));
76   for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
77   {
78     myAxes[anIt].Label.SetFontSize (theCtx, theData.NamesSize());
79   }
80
81   myLabelValues.SetFontSize (theCtx, theData.ValuesSize());
82
83   myAspectLabels.SetFontAspect (theData.NamesFontAspect());
84   myAspectLabels.ChangeFontName() = theData.NamesFont();
85
86   myAspectValues.SetFontAspect (theData.ValuesFontAspect());
87   myAspectValues.ChangeFontName() = theData.ValuesFont();
88
89   // Grid aspect
90   myGridLineAspect.ChangeColor().rgb[0] = (Standard_ShortReal) theData.GridColor().Red();
91   myGridLineAspect.ChangeColor().rgb[1] = (Standard_ShortReal) theData.GridColor().Green();
92   myGridLineAspect.ChangeColor().rgb[2] = (Standard_ShortReal) theData.GridColor().Blue();
93 }
94
95 // =======================================================================
96 // function : Destructor
97 // purpose  :
98 // =======================================================================
99 OpenGl_GraduatedTrihedron::~OpenGl_GraduatedTrihedron()
100 {
101   //
102 }
103
104 // =======================================================================
105 // function : Release
106 // purpose  :
107 // =======================================================================
108 void OpenGl_GraduatedTrihedron::Release (OpenGl_Context* theCtx)
109 {
110   myAxes[0].Release (theCtx);
111   myAxes[1].Release (theCtx);
112   myAxes[2].Release (theCtx);
113   myLabelValues.Release (theCtx);
114 }
115
116 // =======================================================================
117 // method  : getNormal
118 // purpose : Normal of the view (not normalized!)
119 // =======================================================================
120 Standard_ShortReal OpenGl_GraduatedTrihedron::getNormal (const Handle(OpenGl_Context)& theContext,
121                                                          OpenGl_Vec3& theNormal) const
122 {
123   GLint aViewport[4] = {};
124   glGetIntegerv(GL_VIEWPORT, aViewport);
125
126   OpenGl_Mat4 aModelMatrix;
127   OpenGl_Mat4 aProjMatrix;
128   aModelMatrix.Convert (theContext->ModelWorldState.Current() * theContext->WorldViewState.Current());
129   aProjMatrix .Convert (theContext->ProjectionState.Current());
130
131   OpenGl_Vec3 aPoint1, aPoint2, aPoint3;
132   OpenGl_Utils::UnProject<Standard_ShortReal> ((Standard_ShortReal) aViewport[0],
133                                                (Standard_ShortReal) aViewport[1],
134                                                0.0f,
135                                                aModelMatrix, aProjMatrix, aViewport,
136                                                aPoint1.x(), aPoint1.y(), aPoint1.z());
137
138   OpenGl_Utils::UnProject<Standard_ShortReal> ((Standard_ShortReal) (aViewport[0] + aViewport[2]),
139                                                (Standard_ShortReal) aViewport[1],
140                                                0.0f,
141                                                aModelMatrix, aProjMatrix, aViewport,
142                                                aPoint2.x(), aPoint2.y(), aPoint2.z());
143
144   OpenGl_Utils::UnProject<Standard_ShortReal> ((Standard_ShortReal) aViewport[0],
145                                                (Standard_ShortReal) (aViewport[1] + aViewport[3]),
146                                                0.0f,
147                                                aModelMatrix, aProjMatrix, aViewport,
148                                                aPoint3.x(), aPoint3.y(), aPoint3.z());
149
150   const OpenGl_Vec3 aD1 = aPoint3 - aPoint1;
151   const OpenGl_Vec3 aD2 = aPoint2 - aPoint1;
152   theNormal =  OpenGl_Vec3::Cross (aD1, aD2);
153
154   // Distance corresponding to 1 pixel
155   return aD2.Modulus() / (float) aViewport[2];
156 }
157
158 // =======================================================================
159 // method  : getDistancetoCorner
160 // purpose : 
161 // =======================================================================
162 Standard_ShortReal OpenGl_GraduatedTrihedron::getDistanceToCorner (const OpenGl_Vec3& theNormal,
163                                                                    const OpenGl_Vec3& theCenter,
164                                                                    const Standard_ShortReal theX,
165                                                                    const Standard_ShortReal theY,
166                                                                    const Standard_ShortReal theZ) const
167 {
168   return theNormal.x() * (theX - theCenter.x())
169        + theNormal.y() * (theY - theCenter.y())
170        + theNormal.z() * (theZ - theCenter.z());
171 }
172
173 // =======================================================================
174 // method  : getGridAxes
175 // purpose : 
176 // =======================================================================
177 Standard_ExtCharacter OpenGl_GraduatedTrihedron::getGridAxes (const Standard_ShortReal theCorners[8],
178                                                               GridAxes& theGridAxes) const
179 {
180   // Find the farest corner
181   Standard_Byte aMaxIndex = 0;
182   Standard_ShortReal aMax = theCorners[aMaxIndex] > 0.0f ? theCorners[aMaxIndex] : 0.0f;
183
184   for (Standard_Byte anIt = 0; anIt < 8; ++anIt)
185   {
186     if (theCorners[anIt] > aMax)
187     {
188       aMax = theCorners[anIt];
189       aMaxIndex = anIt;
190     }
191   }
192
193   switch (aMaxIndex)
194   {
195     case 0: // (0,0,0)
196     {
197       theGridAxes.Origin = OpenGl_Vec3 (myMin.x(), myMin.y(), myMin.z());
198       theGridAxes.Axes[0] = OpenGl_Vec3 (1.0f, 0.0f, 0.0f);
199       theGridAxes.Axes[1] = OpenGl_Vec3 (0.0f, 1.0f, 0.0f);
200       theGridAxes.Axes[2] = OpenGl_Vec3 (0.0f, 0.0f, 1.0f);
201
202       theGridAxes.Ticks[0] = OpenGl_Vec3 (myMin.x(), myMin.y(), myMax.z());
203       theGridAxes.Ticks[1] = OpenGl_Vec3 (myMax.x(), myMin.y(), myMin.z());
204       theGridAxes.Ticks[2] = OpenGl_Vec3 (myMax.x(), myMin.y(), myMin.z());
205
206       return OOZ_XOZ | OYO_XYO |
207              XOO_XYO | OOZ_OYZ |
208              XOO_XOZ | OYO_OYZ;
209     }
210     case 1: // (0,0,1)
211     {
212       theGridAxes.Origin = OpenGl_Vec3 (myMin.x(), myMin.y(), myMax.z());
213       theGridAxes.Axes[0] = OpenGl_Vec3 (1.0f, 0.0f, 0.0f);
214       theGridAxes.Axes[1] = OpenGl_Vec3 (0.0f, 1.0f, 0.0f);
215       theGridAxes.Axes[2] = OpenGl_Vec3 (0.0f, 0.0f, -1.0f);
216
217       theGridAxes.Ticks[0] = OpenGl_Vec3 (myMin.x(), myMin.y(), myMin.z());
218       theGridAxes.Ticks[1] = OpenGl_Vec3 (myMin.x(), myMin.y(), myMin.z());
219       theGridAxes.Ticks[2] = OpenGl_Vec3 (myMax.x(), myMin.y(), myMax.z());
220
221       return OOZ_XOZ | OYZ_XYZ |
222              OOZ_OYZ | XOZ_XYZ |
223              XOO_XOZ | OYO_OYZ;
224     }
225     case 2: // (0,1,0)
226     {
227       theGridAxes.Origin = OpenGl_Vec3 (myMin.x(), myMax.y(), myMin.z());
228       theGridAxes.Axes[0] = OpenGl_Vec3 (1.0f, 0.0f, 0.0f);
229       theGridAxes.Axes[1] = OpenGl_Vec3 (0.0f, -1.0f, 0.0f);
230       theGridAxes.Axes[2] = OpenGl_Vec3 (0.0f, 0.0f, 1.0f);
231
232       theGridAxes.Ticks[0] = OpenGl_Vec3 (myMin.x(), myMin.y(), myMin.z());
233       theGridAxes.Ticks[1] = OpenGl_Vec3 (myMax.x(), myMax.y(), myMin.z());
234       theGridAxes.Ticks[2] = OpenGl_Vec3 (myMax.x(), myMax.y(), myMin.z());
235
236       return OYO_XYO | OYZ_XYZ |
237              XOO_XYO | OOZ_OYZ |
238              XYO_XYZ | OYO_OYZ;
239     }
240     case 3: // (0,1,1)
241     {
242       theGridAxes.Origin = OpenGl_Vec3 (myMin.x(), myMax.y(), myMax.z());
243       theGridAxes.Axes[0] = OpenGl_Vec3 (1.0f, 0.0f, 0.0f);
244       theGridAxes.Axes[1] = OpenGl_Vec3 (0.0f, -1.0f, 0.0f);
245       theGridAxes.Axes[2] = OpenGl_Vec3 (0.0f, 0.0f, -1.0f);
246
247       theGridAxes.Ticks[0] = OpenGl_Vec3 (myMin.x(), myMin.y(), myMax.z());
248       theGridAxes.Ticks[1] = OpenGl_Vec3 (myMin.x(), myMax.y(), myMin.z());
249       theGridAxes.Ticks[2] = OpenGl_Vec3 (myMin.x(), myMin.y(), myMax.z());
250
251       return OOZ_XOZ | OYZ_XYZ | OYO_XYO |
252              OOZ_OYZ | XOZ_XYZ |
253              OYO_OYZ | XYO_XYZ;
254     }
255     case 4: // (1,0,0)
256     {
257       theGridAxes.Origin = OpenGl_Vec3 (myMax.x(), myMin.y(), myMin.z());
258       theGridAxes.Axes[0] = OpenGl_Vec3 (-1, 0, 0);
259       theGridAxes.Axes[1] = OpenGl_Vec3 (0, 1, 0);
260       theGridAxes.Axes[2] = OpenGl_Vec3 (0, 0, 1);
261
262       theGridAxes.Ticks[0] = OpenGl_Vec3 (myMax.x(), myMin.y(), myMax.z());
263       theGridAxes.Ticks[1] = OpenGl_Vec3 (myMin.x(), myMin.y(), myMin.z());
264       theGridAxes.Ticks[2] = OpenGl_Vec3 (myMin.x(), myMin.y(), myMin.z());
265
266       return OOZ_XOZ | OYO_XYO |
267              XOO_XYO | XOZ_XYZ |
268              XOO_XOZ | XYO_XYZ;
269     }
270     case 5: // (1,0,1)
271     {
272       theGridAxes.Origin = OpenGl_Vec3 (myMax.x(), myMin.y(), myMax.z());
273       theGridAxes.Axes[0] = OpenGl_Vec3 (-1, 0, 0);
274       theGridAxes.Axes[1] = OpenGl_Vec3 (0, 1, 0);
275       theGridAxes.Axes[2] = OpenGl_Vec3 (0, 0, -1);
276
277       theGridAxes.Ticks[0] = OpenGl_Vec3 (myMax.x(), myMin.y(), myMin.z());
278       theGridAxes.Ticks[1] = OpenGl_Vec3 (myMax.x(), myMin.y(), myMin.z());
279       theGridAxes.Ticks[2] = OpenGl_Vec3 (myMin.x(), myMin.y(), myMax.z());
280
281       return OOZ_XOZ | OYZ_XYZ |
282              XOO_XYO | XOZ_XYZ | OOZ_OYZ |
283              XOO_XOZ | XYO_XYZ;
284     }
285     case 6: // (1,1,0)
286     {
287       theGridAxes.Origin = OpenGl_Vec3 (myMax.x(), myMax.y(), myMin.z());
288       theGridAxes.Axes[0] = OpenGl_Vec3 (-1, 0, 0);
289       theGridAxes.Axes[1] = OpenGl_Vec3 (0, -1, 0);
290       theGridAxes.Axes[2] = OpenGl_Vec3 (0, 0, 1);
291
292       theGridAxes.Ticks[0] = OpenGl_Vec3 (myMax.x(), myMin.y(), myMin.z());
293       theGridAxes.Ticks[1] = OpenGl_Vec3 (myMin.x(), myMax.y(), myMin.z());
294       theGridAxes.Ticks[2] = OpenGl_Vec3 (myMax.x(), myMin.y(), myMin.z());
295
296       return OYO_XYO | OYZ_XYZ |
297              XOO_XYO | XOZ_XYZ |
298              XOO_XOZ | XYO_XYZ | OYO_OYZ;
299     }
300     case 7: // (1,1,1)
301     default:
302     {
303       theGridAxes.Origin = OpenGl_Vec3 (myMax.x(), myMax.y(), myMax.z());
304       theGridAxes.Axes[0] = OpenGl_Vec3 (-1, 0, 0);
305       theGridAxes.Axes[1] = OpenGl_Vec3 (0, -1, 0);
306       theGridAxes.Axes[2] = OpenGl_Vec3 (0, 0, -1);
307
308       theGridAxes.Ticks[0] = OpenGl_Vec3 (myMax.x(), myMax.y(), myMin.z());
309       theGridAxes.Ticks[1] = OpenGl_Vec3 (myMax.x(), myMax.y(), myMin.z());
310       theGridAxes.Ticks[2] = OpenGl_Vec3 (myMax.x(), myMin.y(), myMax.z());
311
312       return OYO_XYO | OYZ_XYZ | OOZ_XOZ |
313              XOO_XYO | XOZ_XYZ | OOZ_OYZ |
314              XOO_XOZ | XYO_XYZ | OYO_OYZ;
315     }
316   }
317 }
318
319 // =======================================================================
320 // function : renderLine
321 // purpose  :
322 // =======================================================================
323 void OpenGl_GraduatedTrihedron::renderLine (const OpenGl_PrimitiveArray&    theLine,
324                                             const Handle(OpenGl_Workspace)& theWorkspace,
325                                             const OpenGl_Mat4& theMat,
326                                             const Standard_ShortReal theXt,
327                                             const Standard_ShortReal theYt,
328                                             const Standard_ShortReal theZt) const
329 {
330   const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
331   OpenGl_Mat4 aMat (theMat);
332   OpenGl_Utils::Translate (aMat, theXt, theYt, theZt);
333   aContext->WorldViewState.SetCurrent (aMat);
334   aContext->ApplyWorldViewMatrix();
335   theLine.Render (theWorkspace);
336 }
337
338 // =======================================================================
339 // function : renderGridPlane
340 // purpose  :
341 // =======================================================================
342 void OpenGl_GraduatedTrihedron::renderGridPlane (const Handle(OpenGl_Workspace)& theWorkspace,
343                                                  const Standard_Integer& theIndex,
344                                                  const GridAxes& theGridAxes,
345                                                  OpenGl_Mat4& theMat) const
346 {
347   const Graphic3d_AxisAspect& aCurAspect = myData.AxisAspect (theIndex);
348   if (aCurAspect.TickmarksNumber() <= 0)
349   {
350     return;
351   }
352
353   const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
354
355   Standard_ShortReal aStep = theGridAxes.Axes[theIndex].GetData()[theIndex]
356                             * (myMax.GetData()[theIndex] - myMin.GetData()[theIndex]) / aCurAspect.TickmarksNumber();
357
358   // NOTE:
359   // Get two other axes directions and draw lines Axis.TickmarksNumber times.
360   // Combining together from three axes, these lines will make a grid.
361   for (Standard_Integer anIter = 1; anIter <= 2; ++anIter)
362   {
363     OpenGl_Mat4 aMat (theMat);
364     const Standard_Integer anIndex = (theIndex + anIter) % 3;
365     const Axis& anAxis = myAxes[anIndex];
366     OpenGl_Vec3 aStart (theGridAxes.Origin);
367     if (theGridAxes.Axes[anIndex].GetData()[anIndex] < 0.0)
368     {
369       aStart.ChangeData()[anIndex] = myMin.GetData()[anIndex];
370     }
371
372     OpenGl_Utils::Translate (aMat, aStart.x(), aStart.y(), aStart.z());
373     aContext->WorldViewState.SetCurrent (aMat);
374     aContext->ApplyWorldViewMatrix();
375
376     const OpenGl_Vec3 aStepVec (myAxes[theIndex].Direction * aStep);
377     for (Standard_Integer anIt = myData.ToDrawAxes() ? 1 : 0; anIt < aCurAspect.TickmarksNumber(); ++anIt)
378     {
379       OpenGl_Utils::Translate (aMat, aStepVec.x(), aStepVec.y(), aStepVec.z());
380       aContext->WorldViewState.SetCurrent (aMat);
381       aContext->ApplyWorldViewMatrix();
382       anAxis.Line.Render (theWorkspace);
383     }
384   }
385 }
386
387 // =======================================================================
388 // function : renderAxis
389 // purpose  :
390 // =======================================================================
391 void OpenGl_GraduatedTrihedron::renderAxis (const Handle(OpenGl_Workspace)& theWorkspace,
392                                             const Standard_Integer& theIndex,
393                                             const OpenGl_Mat4& theMat) const
394 {
395   const Axis& anAxis = myAxes[theIndex];
396
397   theWorkspace->SetAspectLine (&anAxis.LineAspect);
398   const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
399
400   // Reset transformations
401   aContext->WorldViewState.SetCurrent (theMat);
402   aContext->ApplyWorldViewMatrix();
403
404   // Render arrow
405
406   TEL_TRANSFORM_PERSISTENCE aTransMode;
407   aTransMode.mode = Graphic3d_TMF_ZoomPers;
408   OpenGl_Vec3 anArrowVec = myMin + anAxis.Direction * (myMax - myMin);
409   aTransMode.pointX = anArrowVec.x();
410   aTransMode.pointY = anArrowVec.y();
411   aTransMode.pointZ = anArrowVec.z();
412
413   theWorkspace->ActiveView()->BeginTransformPersistence (aContext, &aTransMode);
414
415   // NOTE:
416   // OpenGl_View applies Transform Persistence only in Projection Matrix.
417   // Take into account Transform Persistence
418   aContext->ApplyModelViewMatrix();
419
420   // Get current Model-View and Projection states
421   OpenGl_Mat4 aModelMat;
422   OpenGl_Mat4 aProjMat;
423   GLint aViewport[4];
424   aContext->core11fwd->glGetIntegerv (GL_VIEWPORT, aViewport);
425   aModelMat.Convert (aContext->ModelWorldState.Current() * aContext->WorldViewState.Current());
426   aProjMat .Convert (aContext->ProjectionState.Current());
427
428   // Get the window's (fixed) coordinates for before matrixes modifications
429   OpenGl_Vec3 aEndPoint = -anAxis.Direction * myData.ArrowsLength();
430   OpenGl_Vec3 aWinPoint;
431   OpenGl_Utils::Project<Standard_ShortReal> (aEndPoint.x(), aEndPoint.y(), aEndPoint.z(),
432                                              aModelMat, aProjMat, aViewport,
433                                              aWinPoint.x(), aWinPoint.y(), aWinPoint.z());
434   anAxis.Arrow.Render (theWorkspace);
435   theWorkspace->ActiveView()->EndTransformPersistence (aContext);
436
437   // Get current Model-View and Projection states after the end of Transform Persistence
438   aModelMat.Convert (aContext->ModelWorldState.Current() * aContext->WorldViewState.Current());
439   aProjMat .Convert (aContext->ProjectionState.Current());
440
441   // Get start point of zoom persistent arrow
442   OpenGl_Vec3 anArrowStart;
443   OpenGl_Utils::UnProject<Standard_ShortReal> (aWinPoint.x(), aWinPoint.y(), aWinPoint.z(),
444                                                aModelMat, aProjMat, aViewport,
445                                                anArrowStart.x(), anArrowStart.y(), anArrowStart.z());
446   // Render axis line
447
448   aModelMat = theMat;
449   OpenGl_Utils::Translate (aModelMat, myMin.x(), myMin.y(), myMin.z());
450
451   Standard_ShortReal aScaleFactor = ( (anArrowStart - myMin)*anAxis.Direction ).Modulus()
452                                      / (anAxis.Direction * (myMax - myMin) ).Modulus();
453   OpenGl_Vec3 aScaleAxes = anAxis.Direction * aScaleFactor;
454   OpenGl_Utils::Scale (aModelMat, aScaleAxes.x(), aScaleAxes.y(), aScaleAxes.z());
455
456   aContext->WorldViewState.SetCurrent (aModelMat);
457   aContext->ApplyWorldViewMatrix();
458   anAxis.Line.Render (theWorkspace);
459 }
460
461 // =======================================================================
462 // function : renderTickmarkTextLabels
463 // purpose  :
464 // =======================================================================
465 void OpenGl_GraduatedTrihedron::renderTickmarkLabels (const Handle(OpenGl_Workspace)& theWorkspace,
466                                                       const OpenGl_Mat4& theMat,
467                                                       const Standard_Integer theIndex,
468                                                       const GridAxes& theGridAxes,
469                                                       const Standard_ShortReal theDpix) const
470 {
471   const Graphic3d_AxisAspect& aCurAspect = myData.AxisAspect (theIndex);
472   if (!aCurAspect.ToDrawName() && !aCurAspect.ToDrawValues())
473   {
474     return;
475   }
476
477   Standard_Character aTextValue[128];
478   const Axis& anAxis = myAxes[theIndex];
479   const OpenGl_Vec3 aSizeVec (myMax - myMin);
480   Standard_ShortReal aStep = theGridAxes.Axes[theIndex].GetData()[theIndex]
481                        * (myMax.GetData()[theIndex] - myMin.GetData()[theIndex]) / aCurAspect.TickmarksNumber();
482
483   OpenGl_Vec3 aDir = (theGridAxes.Ticks[theIndex] - theGridAxes.Origin).Normalized();
484   const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
485
486   if (aCurAspect.ToDrawTickmarks() && aCurAspect.TickmarksNumber() > 0)
487   {
488     theWorkspace->SetAspectLine (&myGridLineAspect);
489
490     OpenGl_Mat4 aModelMat (theMat);
491
492     anAxis.InitTickmark (aContext, aDir * (Standard_ShortReal) aCurAspect.TickmarksLength() * theDpix);
493     OpenGl_Utils::Translate (aModelMat, theGridAxes.Ticks[theIndex].x(),
494                                         theGridAxes.Ticks[theIndex].y(),
495                                         theGridAxes.Ticks[theIndex].z());
496     aContext->WorldViewState.SetCurrent (aModelMat);
497     aContext->ApplyWorldViewMatrix();
498     OpenGl_Vec3 aStepVec = anAxis.Direction * aStep;
499     for (Standard_Integer anIter = 0; anIter <= aCurAspect.TickmarksNumber(); ++anIter)
500     {
501       anAxis.Tickmark.Render (theWorkspace);
502       OpenGl_Utils::Translate (aModelMat, aStepVec.x(), aStepVec.y(), aStepVec.z());
503       aContext->WorldViewState.SetCurrent (aModelMat);
504       aContext->ApplyWorldViewMatrix();
505     }
506   }
507
508   // Restore matrix
509   aContext->WorldViewState.SetCurrent (theMat);
510   aContext->ApplyWorldViewMatrix();
511
512   if (aCurAspect.ToDrawName())
513   {
514     Standard_Real anOffset = aCurAspect.NameOffset() + aCurAspect.TickmarksLength();
515
516     OpenGl_Vec3 aMiddle (theGridAxes.Ticks[theIndex] + aSizeVec * theGridAxes.Axes[theIndex] * 0.5f + aDir * (Standard_ShortReal)(theDpix * anOffset));
517
518     myAspectLabels.ChangeColor() = anAxis.NameColor;
519     theWorkspace->SetAspectText (&myAspectLabels);
520     anAxis.Label.SetPosition (aMiddle);
521     anAxis.Label.Render (theWorkspace);
522   }
523
524   if (aCurAspect.ToDrawValues() && aCurAspect.TickmarksNumber() > 0)
525   {
526     myAspectValues.ChangeColor() = anAxis.LineAspect.Color();
527     theWorkspace->SetAspectText (&myAspectValues);
528     Standard_Real anOffset = aCurAspect.ValuesOffset() + aCurAspect.TickmarksLength();
529
530     for (Standard_Integer anIt = 0; anIt <= aCurAspect.TickmarksNumber(); ++anIt)
531     {
532       sprintf (aTextValue, "%g", theGridAxes.Ticks[theIndex].GetData()[theIndex] + anIt * aStep);
533       OpenGl_Vec3 aPos (theGridAxes.Ticks[theIndex] + anAxis.Direction* (Standard_ShortReal) (anIt * aStep) + aDir * (Standard_ShortReal) (theDpix * anOffset));
534       myLabelValues.Init (theWorkspace->GetGlContext(), aTextValue, aPos);
535       myLabelValues.Render (theWorkspace);
536     }
537   }
538 }
539
540 // =======================================================================
541 // function : Render
542 // purpose  : call_graduatedtrihedron_redraw
543 // =======================================================================
544 void OpenGl_GraduatedTrihedron::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
545 {
546   const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
547
548   // Update boundary box
549   OpenGl_Vec3 anOldMin = myMin;
550   OpenGl_Vec3 anOldMax = myMax;
551
552   if (myData.CubicAxesCallback)
553   {
554     myData.CubicAxesCallback (myData.PtrVisual3dView);
555     if (!myAxes[0].Line.IsInitialized()
556      || !myAxes[1].Line.IsInitialized()
557      || !myAxes[2].Line.IsInitialized()
558      ||  OpenGl_Vec3 (anOldMin - myMin).Modulus() > Precision::Confusion()
559      ||  OpenGl_Vec3 (anOldMax - myMax).Modulus() > Precision::Confusion())
560     {
561       myAxes[0].InitLine (aContext, OpenGl_Vec3 (myMax.x() - myMin.x(), 0.0f, 0.0f));
562       myAxes[1].InitLine (aContext, OpenGl_Vec3 (0.0f, myMax.y() - myMin.y(), 0.0f));
563       myAxes[2].InitLine (aContext, OpenGl_Vec3 (0.0f, 0.0f, myMax.z() - myMin.z()));
564     }
565   }
566
567   // Find the farest point of bounding box
568
569   // Get normal of the view out of user and distance corresponding to 1 pixel
570   OpenGl_Vec3 aNormal;
571   Standard_ShortReal aDpix = getNormal (aContext, aNormal);
572   aNormal.Normalize();
573
574   // Get central point of bounding box
575   OpenGl_Vec3 aCenter;
576   aCenter = (myMin + myMax) * 0.5f;
577
578   // Check distance to corners of bounding box along the normal
579   Standard_ShortReal aCorners[8];
580   aCorners[0] = getDistanceToCorner (aNormal, aCenter, myMin.x(), myMin.y(), myMin.z());
581   aCorners[1] = getDistanceToCorner (aNormal, aCenter, myMin.x(), myMin.y(), myMax.z());
582   aCorners[2] = getDistanceToCorner (aNormal, aCenter, myMin.x(), myMax.y(), myMin.z());
583   aCorners[3] = getDistanceToCorner (aNormal, aCenter, myMin.x(), myMax.y(), myMax.z());
584   aCorners[4] = getDistanceToCorner (aNormal, aCenter, myMax.x(), myMin.y(), myMin.z());
585   aCorners[5] = getDistanceToCorner (aNormal, aCenter, myMax.x(), myMin.y(), myMax.z());
586   aCorners[6] = getDistanceToCorner (aNormal, aCenter, myMax.x(), myMax.y(), myMin.z());
587   aCorners[7] = getDistanceToCorner (aNormal, aCenter, myMax.x(), myMax.y(), myMax.z());
588
589   // NOTE:
590   // (0, 0, 1), (0, 1, 0) and (0, 0, 1) directions from (myMin.x(), Ymin, Zmin) point
591   // are reserved for trihedron axes.
592   // So for the grid here are 9 edges of cube,
593   // and, depending on the farest point, 2 or 3 of them may not be drawn
594   // if they overlap displayed model.
595   
596   // Write an axes state what axes of bounding box are to be drawn
597   GridAxes aGridAxes;
598   Standard_ExtCharacter anAxesState = getGridAxes (aCorners, aGridAxes);
599
600   // Remember current aspects
601   const OpenGl_AspectLine* anOldAspectLine = theWorkspace->AspectLine (Standard_False);
602   const OpenGl_AspectText* anOldAspectText = theWorkspace->AspectText (Standard_False);
603
604   OpenGl_Mat4 aModelMatrix;
605   aModelMatrix.Convert (aContext->WorldViewState.Current());
606
607   // Remember model-view matrix
608   aContext->WorldViewState.Push();
609   aContext->WorldViewState.SetCurrent (aModelMatrix);
610   aContext->ApplyWorldViewMatrix();
611
612   if (myData.ToDrawGrid())
613   {
614     theWorkspace->SetAspectLine (&myGridLineAspect);
615
616     // render grid edges
617     if (anAxesState & XOO_XYO)
618     {
619       renderLine (myAxes[1].Line, theWorkspace, aModelMatrix, myMax.x(), myMin.y(), myMin.z());
620     }
621
622     if (anAxesState & XOO_XOZ)
623     {
624       renderLine (myAxes[2].Line,theWorkspace, aModelMatrix, myMax.x(), myMin.y(), myMin.z());
625     }
626
627     if (anAxesState & OYO_OYZ)
628     {
629       renderLine (myAxes[2].Line, theWorkspace, aModelMatrix, myMin.x(), myMax.y(), myMin.z());
630     }
631
632     if (anAxesState & OYO_XYO)
633     {
634       renderLine (myAxes[0].Line, theWorkspace, aModelMatrix, myMin.x(), myMax.y(), myMin.z());
635     }
636
637     if (anAxesState & OOZ_XOZ)
638     {
639       renderLine (myAxes[0].Line, theWorkspace, aModelMatrix, myMin.z(), myMin.y(), myMax.z());
640     }
641
642     if (anAxesState & OOZ_OYZ)
643     {
644       renderLine (myAxes[1].Line, theWorkspace, aModelMatrix, myMin.x(), myMin.y(), myMax.z());
645     }
646
647     if (anAxesState & OYZ_XYZ)
648     {
649       renderLine (myAxes[0].Line, theWorkspace, aModelMatrix, myMin.x(), myMax.y(), myMax.z());
650     }
651
652     if (anAxesState & XOZ_XYZ)
653     {
654       renderLine (myAxes[1].Line, theWorkspace, aModelMatrix, myMax.x(), myMin.y(), myMax.z());
655     }
656
657     if (anAxesState & XYO_XYZ)
658     {
659       renderLine (myAxes[2].Line, theWorkspace, aModelMatrix, myMax.x(), myMax.y(), myMin.z());
660     }
661
662     for (Standard_Integer anIter = 0 ; anIter < 3; ++anIter)
663     {
664       renderGridPlane (theWorkspace, anIter, aGridAxes, aModelMatrix);
665     }
666   }
667
668   // Axes (arrows)
669   if (myData.ToDrawAxes())
670   {
671     for (Standard_Integer anIter = 0; anIter < 3; ++anIter)
672     {
673       renderAxis (theWorkspace, anIter, aModelMatrix);
674     }
675   }
676
677   // Names of axes & values
678   for (Standard_Integer anIter = 0; anIter < 3; ++anIter)
679   {
680     // Restore current matrix
681     aContext->WorldViewState.SetCurrent (aModelMatrix);
682     aContext->ApplyWorldViewMatrix();
683     renderTickmarkLabels (theWorkspace, aModelMatrix, anIter, aGridAxes, aDpix);
684   }
685
686   theWorkspace->SetAspectLine (anOldAspectLine);
687   theWorkspace->SetAspectText (anOldAspectText);
688
689   aContext->WorldViewState.Pop();
690   aContext->ApplyWorldViewMatrix();
691 }
692
693 // =======================================================================
694 // method  : SetMinMax
695 // purpose :
696 // =======================================================================
697 void OpenGl_GraduatedTrihedron::SetMinMax (const OpenGl_Vec3& theMin, const OpenGl_Vec3& theMax)
698 {
699   myMin = theMin;
700   myMax = theMax;
701 }
702
703 // =======================================================================
704 // method  : OpenGl_GraduatedTrihedron::Axis constructor
705 // purpose :
706 // =======================================================================
707 OpenGl_GraduatedTrihedron::Axis::Axis (const Graphic3d_AxisAspect& theAspect,
708                                        const OpenGl_Vec3&          theDirection)
709 : Direction (theDirection),
710   Label     (NCollection_String ((Standard_Utf16Char* )theAspect.Name().ToExtString()).ToCString(), theDirection, THE_LABEL_PARAMS),
711   Tickmark  (NULL),
712   Line      (NULL),
713   Arrow     (NULL)
714 {
715   NameColor.rgb[0] = (Standard_ShortReal) theAspect.NameColor().Red();
716   NameColor.rgb[1] = (Standard_ShortReal) theAspect.NameColor().Green();
717   NameColor.rgb[2] = (Standard_ShortReal) theAspect.NameColor().Blue();
718   NameColor.rgb[3] = 1.0f;
719
720   LineAspect.ChangeColor().rgb[0] = (Standard_ShortReal) theAspect.Color().Red();
721   LineAspect.ChangeColor().rgb[1] = (Standard_ShortReal) theAspect.Color().Green();
722   LineAspect.ChangeColor().rgb[2] = (Standard_ShortReal) theAspect.Color().Blue();
723 }
724
725 // =======================================================================
726 // method  : OpenGl_GraduatedTrihedron::Axis::~Axis
727 // purpose :
728 // =======================================================================
729 OpenGl_GraduatedTrihedron::Axis::~Axis()
730 {
731   //
732 }
733
734 // =======================================================================
735 // method  : OpenGl_GraduatedTrihedron::Axis operator=
736 // purpose :
737 // =======================================================================
738 OpenGl_GraduatedTrihedron::Axis& OpenGl_GraduatedTrihedron::Axis::operator= (const Axis& theOther)
739 {
740   Direction  = theOther.Direction;
741   NameColor  = theOther.NameColor;
742   LineAspect = theOther.LineAspect;
743   Label      = theOther.Label;
744
745   Line    .InitBuffers (NULL, Graphic3d_TOPA_SEGMENTS,  theOther.Line.Indices(),     theOther.Line.Attributes(),     theOther.Line.Bounds());
746   Tickmark.InitBuffers (NULL, Graphic3d_TOPA_SEGMENTS,  theOther.Tickmark.Indices(), theOther.Tickmark.Attributes(), theOther.Tickmark.Bounds());
747   Arrow   .InitBuffers (NULL, Graphic3d_TOPA_POLYLINES, theOther.Arrow.Indices(),    theOther.Arrow.Attributes(),    theOther.Arrow.Bounds());
748   return *this;
749 }
750
751 // =======================================================================
752 // method  : InitArrow
753 // purpose :
754 // =======================================================================
755 void OpenGl_GraduatedTrihedron::Axis::InitArrow (const Handle(OpenGl_Context)& theContext,
756                                                  const Standard_ShortReal theLength,
757                                                  const OpenGl_Vec3& theNormal) const
758 {
759   // Draw from the end point of the aris
760   OpenGl_Vec3 aLengthVec = -Direction * theLength;
761
762   // Radial direction to the arrow
763   OpenGl_Vec3 aRadial = OpenGl_Vec3::Cross (this->Direction, theNormal);
764   if (aRadial.Modulus() < (Standard_ShortReal) Precision::Confusion())
765   {
766     return;
767   }
768   aRadial = aRadial.Normalized() * theLength * 0.2f;
769
770   // Initialize arrow primitive array
771   // Make loop from polyline
772   const OpenGl_Vec3 aPoint1 = aRadial + aLengthVec;
773   const OpenGl_Vec3 aPoint2 (0.0f, 0.0f, 0.0f);
774   const OpenGl_Vec3 aPoint3 = -aRadial + aLengthVec;
775
776   Handle(Graphic3d_ArrayOfPolylines) anArray = new Graphic3d_ArrayOfPolylines (4);
777   anArray->AddVertex (aPoint1);
778   anArray->AddVertex (aPoint2);
779   anArray->AddVertex (aPoint3);
780   anArray->AddVertex (aPoint1);
781
782   Arrow.InitBuffers (theContext, Graphic3d_TOPA_POLYLINES,
783                      anArray->Indices(), anArray->Attributes(), anArray->Bounds());
784 }
785
786 // =======================================================================
787 // function : InitTickmark
788 // purpose  :
789 // =======================================================================
790 void OpenGl_GraduatedTrihedron::Axis::InitTickmark (const Handle(OpenGl_Context)& theContext,
791                                                     const OpenGl_Vec3& theDir) const
792 {
793
794   Handle(Graphic3d_ArrayOfSegments) anArray = new Graphic3d_ArrayOfSegments (2);
795   anArray->AddVertex (0.0f, 0.0f, 0.0f);
796   anArray->AddVertex (theDir);
797   Tickmark.InitBuffers (theContext, Graphic3d_TOPA_SEGMENTS,
798                         anArray->Indices(), anArray->Attributes(), anArray->Bounds());
799
800 }
801
802 // =======================================================================
803 // function : InitLine
804 // purpose  :
805 // =======================================================================
806 void OpenGl_GraduatedTrihedron::Axis::InitLine (const Handle(OpenGl_Context)& theContext,
807                                                 const OpenGl_Vec3& theDir) const
808 {
809
810   Handle(Graphic3d_ArrayOfSegments) anArray = new Graphic3d_ArrayOfSegments (2);
811   anArray->AddVertex (0.0f, 0.0f, 0.0f);
812   anArray->AddVertex (theDir);
813
814   Line.InitBuffers (theContext, Graphic3d_TOPA_SEGMENTS,
815                     anArray->Indices(), anArray->Attributes(), anArray->Bounds());
816 }
817
818 // =======================================================================
819 // function : Release
820 // purpose  :
821 // =======================================================================
822 void OpenGl_GraduatedTrihedron::Axis::Release (OpenGl_Context* theCtx)
823 {
824   Label   .Release (theCtx);
825   Tickmark.Release (theCtx);
826   Line    .Release (theCtx);
827   Arrow   .Release (theCtx);
828 }