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