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