1 // Created on: 2011-09-20
2 // Created by: Sergey ZERCHANINOV
3 // Copyright (c) 2011-2013 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
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.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #include <OpenGl_GlCore11.hxx>
18 #include <OpenGl_GraduatedTrihedron.hxx>
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>
26 #include <OpenGl_AspectLine.hxx>
27 #include <OpenGl_Workspace.hxx>
28 #include <OpenGl_View.hxx>
29 #include <Precision.hxx>
37 static const OpenGl_TextParam THE_LABEL_PARAMS =
39 16, Graphic3d_HTA_LEFT, Graphic3d_VTA_BOTTOM
43 // =======================================================================
44 // function : Constructor
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)
55 // =======================================================================
56 // function : SetValues
58 // =======================================================================
59 void OpenGl_GraduatedTrihedron::SetValues (const Graphic3d_GraduatedTrihedron& theData)
62 myIsInitialized = Standard_False;
65 // =======================================================================
66 // function : Destructor
68 // =======================================================================
69 OpenGl_GraduatedTrihedron::~OpenGl_GraduatedTrihedron()
74 // =======================================================================
77 // =======================================================================
78 void OpenGl_GraduatedTrihedron::Release (OpenGl_Context* theCtx)
80 myAxes[0].Release (theCtx);
81 myAxes[1].Release (theCtx);
82 myAxes[2].Release (theCtx);
83 myLabelValues.Release (theCtx);
86 // =======================================================================
87 // function : initResources
89 // =======================================================================
90 void OpenGl_GraduatedTrihedron::initGlResources (const Handle(OpenGl_Context)& theCtx) const
92 myAxes[0].Release (theCtx.operator->());
93 myAxes[1].Release (theCtx.operator->());
94 myAxes[2].Release (theCtx.operator->());
95 myLabelValues.Release (theCtx.operator->());
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));
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)
108 myAxes[anIt].Label.SetFontSize (theCtx, myData.NamesSize());
111 myLabelValues.SetFontSize (theCtx, myData.ValuesSize());
113 myAspectLabels.Aspect()->SetTextFontAspect (myData.NamesFontAspect());
114 myAspectLabels.Aspect()->SetFont (myData.NamesFont());
116 myAspectValues.Aspect()->SetTextFontAspect (myData.ValuesFontAspect());
117 myAspectValues.Aspect()->SetFont (myData.ValuesFont());
120 myGridLineAspect.Aspect()->SetColor (myData.GridColor());
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
130 const Standard_Integer* aViewport = theContext->Viewport();
132 OpenGl_Mat4 aModelMatrix;
133 OpenGl_Mat4 aProjMatrix;
134 aModelMatrix.Convert (theContext->ModelWorldState.Current() * theContext->WorldViewState.Current());
135 aProjMatrix .Convert (theContext->ProjectionState.Current());
137 OpenGl_Vec3 aPoint1, aPoint2, aPoint3;
138 Graphic3d_TransformUtils::UnProject<Standard_ShortReal> ((Standard_ShortReal) aViewport[0],
139 (Standard_ShortReal) aViewport[1],
141 aModelMatrix, aProjMatrix, aViewport,
142 aPoint1.x(), aPoint1.y(), aPoint1.z());
144 Graphic3d_TransformUtils::UnProject<Standard_ShortReal> ((Standard_ShortReal) (aViewport[0] + aViewport[2]),
145 (Standard_ShortReal) aViewport[1],
147 aModelMatrix, aProjMatrix, aViewport,
148 aPoint2.x(), aPoint2.y(), aPoint2.z());
150 Graphic3d_TransformUtils::UnProject<Standard_ShortReal> ((Standard_ShortReal) aViewport[0],
151 (Standard_ShortReal) (aViewport[1] + aViewport[3]),
153 aModelMatrix, aProjMatrix, aViewport,
154 aPoint3.x(), aPoint3.y(), aPoint3.z());
156 const OpenGl_Vec3 aD1 = aPoint3 - aPoint1;
157 const OpenGl_Vec3 aD2 = aPoint2 - aPoint1;
158 theNormal = OpenGl_Vec3::Cross (aD1, aD2);
160 // Distance corresponding to 1 pixel
161 return aD2.Modulus() / (float) aViewport[2];
164 // =======================================================================
165 // method : getDistancetoCorner
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
174 return theNormal.x() * (theX - theCenter.x())
175 + theNormal.y() * (theY - theCenter.y())
176 + theNormal.z() * (theZ - theCenter.z());
179 // =======================================================================
180 // method : getGridAxes
182 // =======================================================================
183 Standard_ExtCharacter OpenGl_GraduatedTrihedron::getGridAxes (const Standard_ShortReal theCorners[8],
184 GridAxes& theGridAxes) const
186 // Find the farest corner
187 Standard_Byte aMaxIndex = 0;
188 Standard_ShortReal aMax = theCorners[aMaxIndex] > 0.0f ? theCorners[aMaxIndex] : 0.0f;
190 for (Standard_Byte anIt = 0; anIt < 8; ++anIt)
192 if (theCorners[anIt] > aMax)
194 aMax = theCorners[anIt];
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);
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());
212 return OOZ_XOZ | OYO_XYO |
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);
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());
227 return OOZ_XOZ | OYZ_XYZ |
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);
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());
242 return OYO_XYO | OYZ_XYZ |
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);
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());
257 return OOZ_XOZ | OYZ_XYZ | OYO_XYO |
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);
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());
272 return OOZ_XOZ | OYO_XYO |
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);
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());
287 return OOZ_XOZ | OYZ_XYZ |
288 XOO_XYO | XOZ_XYZ | OOZ_OYZ |
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);
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());
302 return OYO_XYO | OYZ_XYZ |
304 XOO_XOZ | XYO_XYZ | OYO_OYZ;
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);
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());
318 return OYO_XYO | OYZ_XYZ | OOZ_XOZ |
319 XOO_XYO | XOZ_XYZ | OOZ_OYZ |
320 XOO_XOZ | XYO_XYZ | OYO_OYZ;
325 // =======================================================================
326 // function : renderLine
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
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);
344 // =======================================================================
345 // function : renderGridPlane
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
353 const Graphic3d_AxisAspect& aCurAspect = myData.AxisAspect (theIndex);
354 if (aCurAspect.TickmarksNumber() <= 0)
359 const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
361 Standard_ShortReal aStep = theGridAxes.Axes[theIndex].GetData()[theIndex]
362 * (myMax.GetData()[theIndex] - myMin.GetData()[theIndex]) / aCurAspect.TickmarksNumber();
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)
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)
375 aStart.ChangeData()[anIndex] = myMin.GetData()[anIndex];
378 Graphic3d_TransformUtils::Translate (aMat, aStart.x(), aStart.y(), aStart.z());
379 aContext->WorldViewState.SetCurrent (aMat);
380 aContext->ApplyWorldViewMatrix();
382 const OpenGl_Vec3 aStepVec (myAxes[theIndex].Direction * aStep);
383 for (Standard_Integer anIt = myData.ToDrawAxes() ? 1 : 0; anIt < aCurAspect.TickmarksNumber(); ++anIt)
385 Graphic3d_TransformUtils::Translate (aMat, aStepVec.x(), aStepVec.y(), aStepVec.z());
386 aContext->WorldViewState.SetCurrent (aMat);
387 aContext->ApplyWorldViewMatrix();
388 anAxis.Line.Render (theWorkspace);
393 // =======================================================================
394 // function : renderAxis
396 // =======================================================================
397 void OpenGl_GraduatedTrihedron::renderAxis (const Handle(OpenGl_Workspace)& theWorkspace,
398 const Standard_Integer& theIndex,
399 const OpenGl_Mat4& theMat) const
401 const Axis& anAxis = myAxes[theIndex];
403 theWorkspace->SetAspectLine (&anAxis.LineAspect);
404 const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
406 // Reset transformations
407 aContext->WorldViewState.SetCurrent (theMat);
408 aContext->ApplyWorldViewMatrix();
411 OpenGl_Vec3 anArrowVec = myMin + anAxis.Direction * (myMax - myMin);
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();
421 // Take into account Transform Persistence
422 aContext->ModelWorldState.SetCurrent (aTransMode.Compute (theWorkspace->View()->Camera(), aProjection, aWorldView, aWidth, aHeight));
423 aContext->ApplyModelViewMatrix();
425 anAxis.Arrow.Render (theWorkspace);
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());
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());
440 aContext->ModelWorldState.SetIdentity();
441 aModelMat.Convert (aContext->WorldViewState.Current());
442 aProjMat .Convert (aContext->ProjectionState.Current());
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());
451 Graphic3d_TransformUtils::Translate (aModelMat, myMin.x(), myMin.y(), myMin.z());
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());
458 aContext->WorldViewState.SetCurrent (aModelMat);
459 aContext->ApplyWorldViewMatrix();
460 anAxis.Line.Render (theWorkspace);
463 // =======================================================================
464 // function : renderTickmarkTextLabels
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
473 const Graphic3d_AxisAspect& aCurAspect = myData.AxisAspect (theIndex);
474 if (!aCurAspect.ToDrawName() && !aCurAspect.ToDrawValues())
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();
485 OpenGl_Vec3 aDir = (theGridAxes.Ticks[theIndex] - theGridAxes.Origin).Normalized();
486 const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
488 if (aCurAspect.ToDrawTickmarks() && aCurAspect.TickmarksNumber() > 0)
490 theWorkspace->SetAspectLine (&myGridLineAspect);
492 OpenGl_Mat4 aModelMat (theMat);
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)
503 anAxis.Tickmark.Render (theWorkspace);
504 Graphic3d_TransformUtils::Translate (aModelMat, aStepVec.x(), aStepVec.y(), aStepVec.z());
505 aContext->WorldViewState.SetCurrent (aModelMat);
506 aContext->ApplyWorldViewMatrix();
511 aContext->WorldViewState.SetCurrent (theMat);
512 aContext->ApplyWorldViewMatrix();
514 if (aCurAspect.ToDrawName())
516 Standard_Real anOffset = aCurAspect.NameOffset() + aCurAspect.TickmarksLength();
518 OpenGl_Vec3 aMiddle (theGridAxes.Ticks[theIndex] + aSizeVec * theGridAxes.Axes[theIndex] * 0.5f + aDir * (Standard_ShortReal)(theDpix * anOffset));
520 myAspectLabels.Aspect()->SetColor (anAxis.NameColor);
521 theWorkspace->SetAspectText (&myAspectLabels);
522 anAxis.Label.SetPosition (aMiddle);
523 anAxis.Label.Render (theWorkspace);
526 if (aCurAspect.ToDrawValues() && aCurAspect.TickmarksNumber() > 0)
528 myAspectValues.Aspect()->SetColor (anAxis.LineAspect.Aspect()->Color());
529 theWorkspace->SetAspectText (&myAspectValues);
530 Standard_Real anOffset = aCurAspect.ValuesOffset() + aCurAspect.TickmarksLength();
532 for (Standard_Integer anIt = 0; anIt <= aCurAspect.TickmarksNumber(); ++anIt)
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);
542 // =======================================================================
544 // purpose : call_graduatedtrihedron_redraw
545 // =======================================================================
546 void OpenGl_GraduatedTrihedron::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
548 const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
549 if (!myIsInitialized)
551 initGlResources (theWorkspace->GetGlContext());
552 myIsInitialized = Standard_True;
555 // Update boundary box
556 OpenGl_Vec3 anOldMin = myMin;
557 OpenGl_Vec3 anOldMax = myMax;
559 if (myData.CubicAxesCallback)
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())
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()));
574 // Find the farest point of bounding box
576 // Get normal of the view out of user and distance corresponding to 1 pixel
578 Standard_ShortReal aDpix = getNormal (aContext, aNormal);
581 // Get central point of bounding box
583 aCenter = (myMin + myMax) * 0.5f;
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());
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.
603 // Write an axes state what axes of bounding box are to be drawn
605 Standard_ExtCharacter anAxesState = getGridAxes (aCorners, aGridAxes);
607 // Remember current aspects
608 const OpenGl_AspectLine* anOldAspectLine = theWorkspace->AspectLine();
609 const OpenGl_AspectText* anOldAspectText = theWorkspace->AspectText();
611 OpenGl_Mat4 aModelMatrix;
612 aModelMatrix.Convert (aContext->WorldViewState.Current());
614 // Remember model-view matrix
615 aContext->WorldViewState.Push();
616 aContext->WorldViewState.SetCurrent (aModelMatrix);
617 aContext->ApplyWorldViewMatrix();
619 if (myData.ToDrawGrid())
621 theWorkspace->SetAspectLine (&myGridLineAspect);
624 if (anAxesState & XOO_XYO)
626 renderLine (myAxes[1].Line, theWorkspace, aModelMatrix, myMax.x(), myMin.y(), myMin.z());
629 if (anAxesState & XOO_XOZ)
631 renderLine (myAxes[2].Line,theWorkspace, aModelMatrix, myMax.x(), myMin.y(), myMin.z());
634 if (anAxesState & OYO_OYZ)
636 renderLine (myAxes[2].Line, theWorkspace, aModelMatrix, myMin.x(), myMax.y(), myMin.z());
639 if (anAxesState & OYO_XYO)
641 renderLine (myAxes[0].Line, theWorkspace, aModelMatrix, myMin.x(), myMax.y(), myMin.z());
644 if (anAxesState & OOZ_XOZ)
646 renderLine (myAxes[0].Line, theWorkspace, aModelMatrix, myMin.z(), myMin.y(), myMax.z());
649 if (anAxesState & OOZ_OYZ)
651 renderLine (myAxes[1].Line, theWorkspace, aModelMatrix, myMin.x(), myMin.y(), myMax.z());
654 if (anAxesState & OYZ_XYZ)
656 renderLine (myAxes[0].Line, theWorkspace, aModelMatrix, myMin.x(), myMax.y(), myMax.z());
659 if (anAxesState & XOZ_XYZ)
661 renderLine (myAxes[1].Line, theWorkspace, aModelMatrix, myMax.x(), myMin.y(), myMax.z());
664 if (anAxesState & XYO_XYZ)
666 renderLine (myAxes[2].Line, theWorkspace, aModelMatrix, myMax.x(), myMax.y(), myMin.z());
669 for (Standard_Integer anIter = 0 ; anIter < 3; ++anIter)
671 renderGridPlane (theWorkspace, anIter, aGridAxes, aModelMatrix);
676 if (myData.ToDrawAxes())
678 for (Standard_Integer anIter = 0; anIter < 3; ++anIter)
680 renderAxis (theWorkspace, anIter, aModelMatrix);
684 // Names of axes & values
685 for (Standard_Integer anIter = 0; anIter < 3; ++anIter)
687 // Restore current matrix
688 aContext->WorldViewState.SetCurrent (aModelMatrix);
689 aContext->ApplyWorldViewMatrix();
690 renderTickmarkLabels (theWorkspace, aModelMatrix, anIter, aGridAxes, aDpix);
693 theWorkspace->SetAspectLine (anOldAspectLine);
694 theWorkspace->SetAspectText (anOldAspectText);
696 aContext->WorldViewState.Pop();
697 aContext->ApplyWorldViewMatrix();
700 // =======================================================================
701 // method : SetMinMax
703 // =======================================================================
704 void OpenGl_GraduatedTrihedron::SetMinMax (const OpenGl_Vec3& theMin, const OpenGl_Vec3& theMax)
710 // =======================================================================
711 // method : OpenGl_GraduatedTrihedron::Axis constructor
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),
722 NameColor = theAspect.NameColor();
723 LineAspect.Aspect()->SetColor (theAspect.Color());
726 // =======================================================================
727 // method : OpenGl_GraduatedTrihedron::Axis::~Axis
729 // =======================================================================
730 OpenGl_GraduatedTrihedron::Axis::~Axis()
735 // =======================================================================
736 // method : OpenGl_GraduatedTrihedron::Axis operator=
738 // =======================================================================
739 OpenGl_GraduatedTrihedron::Axis& OpenGl_GraduatedTrihedron::Axis::operator= (const Axis& theOther)
741 Direction = theOther.Direction;
742 NameColor = theOther.NameColor;
743 LineAspect = theOther.LineAspect;
744 Label = theOther.Label;
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());
752 // =======================================================================
753 // method : InitArrow
755 // =======================================================================
756 void OpenGl_GraduatedTrihedron::Axis::InitArrow (const Handle(OpenGl_Context)& theContext,
757 const Standard_ShortReal theLength,
758 const OpenGl_Vec3& theNormal) const
760 // Draw from the end point of the aris
761 OpenGl_Vec3 aLengthVec = -Direction * theLength;
763 // Radial direction to the arrow
764 OpenGl_Vec3 aRadial = OpenGl_Vec3::Cross (this->Direction, theNormal);
765 if (aRadial.Modulus() < (Standard_ShortReal) Precision::Confusion())
769 aRadial = aRadial.Normalized() * theLength * 0.2f;
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;
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);
783 Arrow.InitBuffers (theContext, Graphic3d_TOPA_POLYLINES,
784 anArray->Indices(), anArray->Attributes(), anArray->Bounds());
787 // =======================================================================
788 // function : InitTickmark
790 // =======================================================================
791 void OpenGl_GraduatedTrihedron::Axis::InitTickmark (const Handle(OpenGl_Context)& theContext,
792 const OpenGl_Vec3& theDir) const
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());
803 // =======================================================================
804 // function : InitLine
806 // =======================================================================
807 void OpenGl_GraduatedTrihedron::Axis::InitLine (const Handle(OpenGl_Context)& theContext,
808 const OpenGl_Vec3& theDir) const
811 Handle(Graphic3d_ArrayOfSegments) anArray = new Graphic3d_ArrayOfSegments (2);
812 anArray->AddVertex (0.0f, 0.0f, 0.0f);
813 anArray->AddVertex (theDir);
815 Line.InitBuffers (theContext, Graphic3d_TOPA_SEGMENTS,
816 anArray->Indices(), anArray->Attributes(), anArray->Bounds());
819 // =======================================================================
820 // function : Release
822 // =======================================================================
823 void OpenGl_GraduatedTrihedron::Axis::Release (OpenGl_Context* theCtx)
825 Label .Release (theCtx);
826 Tickmark.Release (theCtx);
827 Line .Release (theCtx);
828 Arrow .Release (theCtx);