Commit | Line | Data |
---|---|---|
b311480e | 1 | // Created on: 2011-07-13 |
2 | // Created by: Sergey ZERCHANINOV | |
a174a3c5 | 3 | // Copyright (c) 2011-2013 OPEN CASCADE SAS |
b311480e | 4 | // |
973c2be1 | 5 | // This file is part of Open CASCADE Technology software library. |
b311480e | 6 | // |
d5f74e42 | 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 | |
973c2be1 | 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. | |
b311480e | 12 | // |
973c2be1 | 13 | // Alternatively, this file may be used under the terms of Open CASCADE |
14 | // commercial license or contractual agreement. | |
b311480e | 15 | |
bf5f0ca2 | 16 | #include <OpenGl_Aspects.hxx> |
30f0ad28 | 17 | #include <OpenGl_GlCore11.hxx> |
a174a3c5 | 18 | #include <OpenGl_GraphicDriver.hxx> |
30f0ad28 | 19 | #include <OpenGl_ShaderManager.hxx> |
20 | #include <OpenGl_ShaderProgram.hxx> | |
21 | #include <OpenGl_ShaderStates.hxx> | |
22 | #include <OpenGl_Text.hxx> | |
bf75be98 | 23 | #include <OpenGl_Workspace.hxx> |
ce01ec26 | 24 | #include <OpenGl_View.hxx> |
048e1b3b | 25 | #include <OpenGl_VertexBufferCompat.hxx> |
2166f0fa | 26 | |
a174a3c5 | 27 | #include <Font_FontMgr.hxx> |
d2eddacc | 28 | #include <Font_FTFont.hxx> |
825aa485 | 29 | #include <Graphic3d_TransformUtils.hxx> |
a174a3c5 | 30 | #include <TCollection_HAsciiString.hxx> |
31 | ||
a174a3c5 | 32 | namespace |
2166f0fa | 33 | { |
a3a3ff3d | 34 | static const OpenGl_Mat4d THE_IDENTITY_MATRIX; |
a174a3c5 | 35 | |
bf5f0ca2 | 36 | static const TCollection_AsciiString THE_DEFAULT_FONT (Font_NOF_ASCII_MONO); |
37 | ||
8d1a539c | 38 | //! Auxiliary tool for setting polygon offset temporarily. |
39 | struct BackPolygonOffsetSentry | |
40 | { | |
1f44d29a | 41 | BackPolygonOffsetSentry (OpenGl_Context* theCtx) |
42 | : myCtx (theCtx) | |
8d1a539c | 43 | { |
1f44d29a | 44 | if (theCtx != NULL) |
8d1a539c | 45 | { |
1f44d29a | 46 | myOffsetBack = theCtx->PolygonOffset(); |
8d1a539c | 47 | Graphic3d_PolygonOffset aPolyOffset = myOffsetBack; |
48 | aPolyOffset.Mode = Aspect_POM_Fill; | |
49 | aPolyOffset.Units += 1.0f; | |
50 | theCtx->SetPolygonOffset (aPolyOffset); | |
51 | } | |
52 | } | |
53 | ||
54 | ~BackPolygonOffsetSentry() | |
55 | { | |
1f44d29a | 56 | if (myCtx != NULL) |
8d1a539c | 57 | { |
58 | myCtx->SetPolygonOffset (myOffsetBack); | |
59 | } | |
60 | } | |
61 | ||
62 | private: | |
63 | BackPolygonOffsetSentry (const BackPolygonOffsetSentry& ); | |
64 | BackPolygonOffsetSentry& operator= (const BackPolygonOffsetSentry& ); | |
65 | private: | |
1f44d29a | 66 | OpenGl_Context* myCtx; |
67 | Graphic3d_PolygonOffset myOffsetBack; | |
8d1a539c | 68 | }; |
69 | ||
68858c7d | 70 | } // anonymous namespace |
a174a3c5 | 71 | |
72 | // ======================================================================= | |
73 | // function : OpenGl_Text | |
74 | // purpose : | |
75 | // ======================================================================= | |
76 | OpenGl_Text::OpenGl_Text() | |
a3a3ff3d | 77 | : myScaleHeight (1.0f), |
8ed07085 | 78 | myIs2d (Standard_False) |
a174a3c5 | 79 | { |
8ed07085 | 80 | myText = new Graphic3d_Text (10.); |
2166f0fa SK |
81 | } |
82 | ||
2166f0fa | 83 | |
ce01ec26 | 84 | // ======================================================================= |
85 | // function : OpenGl_Text | |
86 | // purpose : | |
87 | // ======================================================================= | |
8ed07085 | 88 | OpenGl_Text::OpenGl_Text (const Handle(Graphic3d_Text)& theTextParams) |
89 | : myText (theTextParams), | |
90 | myScaleHeight (1.0f), | |
91 | myIs2d (Standard_False) | |
ce01ec26 | 92 | { |
ce01ec26 | 93 | } |
94 | ||
a174a3c5 | 95 | // ======================================================================= |
96 | // function : SetPosition | |
97 | // purpose : | |
98 | // ======================================================================= | |
99 | void OpenGl_Text::SetPosition (const OpenGl_Vec3& thePoint) | |
2166f0fa | 100 | { |
8ed07085 | 101 | myText->SetPosition (gp_Pnt (thePoint.x(), thePoint.y(), thePoint.z())); |
2166f0fa SK |
102 | } |
103 | ||
a174a3c5 | 104 | // ======================================================================= |
105 | // function : SetFontSize | |
106 | // purpose : | |
107 | // ======================================================================= | |
108 | void OpenGl_Text::SetFontSize (const Handle(OpenGl_Context)& theCtx, | |
109 | const Standard_Integer theFontSize) | |
110 | { | |
8ed07085 | 111 | if (myText->Height() != theFontSize) |
a174a3c5 | 112 | { |
10b9c7df | 113 | Release (theCtx.operator->()); |
a174a3c5 | 114 | } |
8ed07085 | 115 | myText->SetHeight ((Standard_ShortReal)theFontSize); |
a174a3c5 | 116 | } |
117 | ||
118 | // ======================================================================= | |
8ed07085 | 119 | // function : Reset |
a174a3c5 | 120 | // purpose : |
121 | // ======================================================================= | |
8ed07085 | 122 | void OpenGl_Text::Reset (const Handle(OpenGl_Context)& theCtx) |
a174a3c5 | 123 | { |
8ed07085 | 124 | if (!myFont.IsNull() && myFont->FTFont()->PointSize() != myText->Height()) |
a174a3c5 | 125 | { |
10b9c7df | 126 | Release (theCtx.operator->()); |
a174a3c5 | 127 | } |
128 | else | |
129 | { | |
10b9c7df | 130 | releaseVbos (theCtx.operator->()); |
a174a3c5 | 131 | } |
a174a3c5 | 132 | } |
2166f0fa | 133 | |
a174a3c5 | 134 | // ======================================================================= |
135 | // function : Init | |
136 | // purpose : | |
137 | // ======================================================================= | |
8ed07085 | 138 | void OpenGl_Text::Init (const Handle(OpenGl_Context)& theCtx, |
139 | const Standard_Utf8Char* theText, | |
140 | const OpenGl_Vec3& thePoint) | |
2166f0fa | 141 | { |
8ed07085 | 142 | Reset (theCtx); |
143 | Set2D (Standard_False); | |
144 | ||
145 | NCollection_String aText; | |
146 | aText.FromUnicode (theText); | |
147 | myText->SetText (aText); | |
148 | myText->SetPosition (gp_Pnt (thePoint.x(), thePoint.y(), thePoint.z())); | |
a174a3c5 | 149 | } |
150 | ||
151 | // ======================================================================= | |
152 | // function : ~OpenGl_Text | |
153 | // purpose : | |
154 | // ======================================================================= | |
155 | OpenGl_Text::~OpenGl_Text() | |
156 | { | |
157 | // | |
158 | } | |
159 | ||
160 | // ======================================================================= | |
161 | // function : releaseVbos | |
162 | // purpose : | |
163 | // ======================================================================= | |
10b9c7df | 164 | void OpenGl_Text::releaseVbos (OpenGl_Context* theCtx) |
a174a3c5 | 165 | { |
166 | for (Standard_Integer anIter = 0; anIter < myVertsVbo.Length(); ++anIter) | |
167 | { | |
168 | Handle(OpenGl_VertexBuffer)& aVerts = myVertsVbo.ChangeValue (anIter); | |
169 | Handle(OpenGl_VertexBuffer)& aTCrds = myTCrdsVbo.ChangeValue (anIter); | |
170 | ||
6fe58c66 | 171 | if (theCtx != NULL) |
a174a3c5 | 172 | { |
173 | theCtx->DelayedRelease (aVerts); | |
174 | theCtx->DelayedRelease (aTCrds); | |
175 | } | |
176 | aVerts.Nullify(); | |
177 | aTCrds.Nullify(); | |
178 | } | |
6fe58c66 | 179 | if (theCtx != NULL |
180 | && !myBndVertsVbo.IsNull()) | |
181 | { | |
182 | theCtx->DelayedRelease (myBndVertsVbo); | |
183 | } | |
184 | ||
a174a3c5 | 185 | myTextures.Clear(); |
186 | myVertsVbo.Clear(); | |
187 | myTCrdsVbo.Clear(); | |
6fe58c66 | 188 | myBndVertsVbo.Nullify(); |
a174a3c5 | 189 | } |
190 | ||
191 | // ======================================================================= | |
192 | // function : Release | |
193 | // purpose : | |
194 | // ======================================================================= | |
10b9c7df | 195 | void OpenGl_Text::Release (OpenGl_Context* theCtx) |
a174a3c5 | 196 | { |
197 | releaseVbos (theCtx); | |
198 | if (!myFont.IsNull()) | |
199 | { | |
a174a3c5 | 200 | const TCollection_AsciiString aKey = myFont->ResourceKey(); |
201 | myFont.Nullify(); | |
6fe58c66 | 202 | if (theCtx != NULL) |
203 | { | |
204 | theCtx->ReleaseResource (aKey, Standard_True); | |
205 | } | |
a174a3c5 | 206 | } |
207 | } | |
208 | ||
3d60d73f | 209 | // ======================================================================= |
210 | // function : EstimatedDataSize | |
211 | // purpose : | |
212 | // ======================================================================= | |
213 | Standard_Size OpenGl_Text::EstimatedDataSize() const | |
214 | { | |
215 | Standard_Size aSize = 0; | |
216 | for (Standard_Integer anIter = myVertsVbo.Lower(); anIter <= myVertsVbo.Upper(); ++anIter) | |
217 | { | |
218 | if (const Handle(OpenGl_VertexBuffer)& aVerts = myVertsVbo.Value (anIter)) | |
219 | { | |
220 | aSize += aVerts->EstimatedDataSize(); | |
221 | } | |
222 | if (const Handle(OpenGl_VertexBuffer)& aTCrds = myTCrdsVbo.Value (anIter)) | |
223 | { | |
224 | aSize += aTCrds->EstimatedDataSize(); | |
225 | } | |
226 | } | |
227 | if (!myBndVertsVbo.IsNull()) | |
228 | { | |
229 | aSize += myBndVertsVbo->EstimatedDataSize(); | |
230 | } | |
231 | return aSize; | |
232 | } | |
233 | ||
b9f43ad1 | 234 | // ======================================================================= |
235 | // function : UpdateDrawStats | |
236 | // purpose : | |
237 | // ======================================================================= | |
238 | void OpenGl_Text::UpdateDrawStats (Graphic3d_FrameStatsDataTmp& theStats, | |
239 | bool theIsDetailed) const | |
240 | { | |
241 | ++theStats[Graphic3d_FrameStatsCounter_NbElemsNotCulled]; | |
242 | ++theStats[Graphic3d_FrameStatsCounter_NbElemsTextNotCulled]; | |
243 | if (theIsDetailed) | |
244 | { | |
245 | for (Standard_Integer anIter = myVertsVbo.Lower(); anIter <= myVertsVbo.Upper(); ++anIter) | |
246 | { | |
247 | if (const Handle(OpenGl_VertexBuffer)& aVerts = myVertsVbo.Value (anIter)) | |
248 | { | |
249 | theStats[Graphic3d_FrameStatsCounter_NbTrianglesNotCulled] += aVerts->GetElemsNb() / 3; // 2 non-indexed triangles per glyph | |
250 | } | |
251 | } | |
252 | } | |
253 | } | |
254 | ||
a174a3c5 | 255 | // ======================================================================= |
256 | // function : StringSize | |
257 | // purpose : | |
258 | // ======================================================================= | |
259 | void OpenGl_Text::StringSize (const Handle(OpenGl_Context)& theCtx, | |
260 | const NCollection_String& theText, | |
bf5f0ca2 | 261 | const OpenGl_Aspects& theTextAspect, |
8ed07085 | 262 | const Standard_ShortReal theHeight, |
4b1c8733 | 263 | const unsigned int theResolution, |
a174a3c5 | 264 | Standard_ShortReal& theWidth, |
265 | Standard_ShortReal& theAscent, | |
266 | Standard_ShortReal& theDescent) | |
267 | { | |
268 | theWidth = 0.0f; | |
269 | theAscent = 0.0f; | |
270 | theDescent = 0.0f; | |
8ed07085 | 271 | const TCollection_AsciiString aFontKey = FontKey (theTextAspect, (Standard_Integer)theHeight, theResolution); |
272 | Handle(OpenGl_Font) aFont = FindFont (theCtx, theTextAspect, (Standard_Integer)theHeight, theResolution, aFontKey); | |
a174a3c5 | 273 | if (aFont.IsNull() || !aFont->IsValid()) |
274 | { | |
2166f0fa | 275 | return; |
a174a3c5 | 276 | } |
277 | ||
278 | theAscent = aFont->Ascender(); | |
279 | theDescent = aFont->Descender(); | |
280 | ||
281 | GLfloat aWidth = 0.0f; | |
282 | for (NCollection_Utf8Iter anIter = theText.Iterator(); *anIter != 0;) | |
283 | { | |
284 | const Standard_Utf32Char aCharThis = *anIter; | |
285 | const Standard_Utf32Char aCharNext = *++anIter; | |
286 | ||
287 | if (aCharThis == '\x0D' // CR (carriage return) | |
288 | || aCharThis == '\a' // BEL (alarm) | |
289 | || aCharThis == '\f' // FF (form feed) NP (new page) | |
290 | || aCharThis == '\b' // BS (backspace) | |
291 | || aCharThis == '\v') // VT (vertical tab) | |
292 | { | |
293 | continue; // skip unsupported carriage control codes | |
294 | } | |
295 | else if (aCharThis == '\x0A') // LF (line feed, new line) | |
296 | { | |
297 | theWidth = Max (theWidth, aWidth); | |
298 | aWidth = 0.0f; | |
299 | continue; | |
300 | } | |
301 | else if (aCharThis == ' ') | |
302 | { | |
d2eddacc | 303 | aWidth += aFont->FTFont()->AdvanceX (aCharThis, aCharNext); |
a174a3c5 | 304 | continue; |
305 | } | |
306 | else if (aCharThis == '\t') | |
307 | { | |
d2eddacc | 308 | aWidth += aFont->FTFont()->AdvanceX (' ', aCharNext) * 8.0f; |
a174a3c5 | 309 | continue; |
310 | } | |
311 | ||
d2eddacc | 312 | aWidth += aFont->FTFont()->AdvanceX (aCharThis, aCharNext); |
a174a3c5 | 313 | } |
314 | theWidth = Max (theWidth, aWidth); | |
315 | ||
316 | Handle(OpenGl_Context) aCtx = theCtx; | |
317 | aFont.Nullify(); | |
318 | aCtx->ReleaseResource (aFontKey, Standard_True); | |
319 | } | |
320 | ||
321 | // ======================================================================= | |
322 | // function : Render | |
323 | // purpose : | |
324 | // ======================================================================= | |
325 | void OpenGl_Text::Render (const Handle(OpenGl_Workspace)& theWorkspace) const | |
326 | { | |
72f6dc61 | 327 | const OpenGl_Aspects* aTextAspect = theWorkspace->ApplyAspects (false); // do not bind textures as they will be disabled anyway |
bf5f0ca2 | 328 | const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext(); |
8d1a539c | 329 | |
b990e557 | 330 | // Bind custom shader program or generate default version |
8613985b | 331 | aCtx->ShaderManager()->BindFontProgram (aTextAspect->ShaderProgramRes (aCtx)); |
72f6dc61 | 332 | const Handle(OpenGl_TextureSet) aPrevTexture = aCtx->BindTextures (Handle(OpenGl_TextureSet)(), Handle(OpenGl_ShaderProgram)()); |
30f0ad28 | 333 | |
8ed07085 | 334 | if (myText->HasPlane() && myText->HasOwnAnchorPoint()) |
a3a3ff3d | 335 | { |
336 | myOrientationMatrix = theWorkspace->View()->Camera()->OrientationMatrix(); | |
337 | // reset translation part | |
338 | myOrientationMatrix.ChangeValue (0, 3) = 0.0; | |
339 | myOrientationMatrix.ChangeValue (1, 3) = 0.0; | |
340 | myOrientationMatrix.ChangeValue (2, 3) = 0.0; | |
341 | } | |
342 | ||
ce01ec26 | 343 | myProjMatrix.Convert (aCtx->ProjectionState.Current()); |
344 | ||
a174a3c5 | 345 | // use highlight color or colors from aspect |
60273f77 | 346 | render (aCtx, |
f9ba5c4d | 347 | *aTextAspect, |
348 | theWorkspace->TextColor(), | |
349 | theWorkspace->TextSubtitleColor(), | |
56689b27 | 350 | aCtx->Resolution()); |
2166f0fa | 351 | |
a174a3c5 | 352 | // restore aspects |
353 | if (!aPrevTexture.IsNull()) | |
354 | { | |
72f6dc61 | 355 | aCtx->BindTextures (aPrevTexture, Handle(OpenGl_ShaderProgram)()); |
a174a3c5 | 356 | } |
b34efb62 | 357 | |
358 | // restore Z buffer settings | |
eae454e3 | 359 | if (theWorkspace->UseZBuffer()) |
b34efb62 | 360 | { |
361 | glEnable (GL_DEPTH_TEST); | |
362 | } | |
a174a3c5 | 363 | } |
2166f0fa | 364 | |
a174a3c5 | 365 | // ======================================================================= |
366 | // function : Render | |
367 | // purpose : | |
368 | // ======================================================================= | |
60273f77 | 369 | void OpenGl_Text::Render (const Handle(OpenGl_Context)& theCtx, |
bf5f0ca2 | 370 | const OpenGl_Aspects& theTextAspect, |
371 | unsigned int theResolution) const | |
a174a3c5 | 372 | { |
2a332745 | 373 | #if !defined(GL_ES_VERSION_2_0) |
374 | const Standard_Integer aPrevPolygonMode = theCtx->SetPolygonMode (GL_FILL); | |
375 | const bool aPrevHatchingMode = theCtx->SetPolygonHatchEnabled (false); | |
376 | #endif | |
377 | ||
60273f77 | 378 | render (theCtx, theTextAspect, |
b6472664 | 379 | theTextAspect.Aspect()->ColorRGBA(), |
380 | theTextAspect.Aspect()->ColorSubTitleRGBA(), | |
381 | theResolution); | |
2a332745 | 382 | |
383 | #if !defined(GL_ES_VERSION_2_0) | |
384 | theCtx->SetPolygonMode (aPrevPolygonMode); | |
385 | theCtx->SetPolygonHatchEnabled (aPrevHatchingMode); | |
386 | #endif | |
a174a3c5 | 387 | } |
2166f0fa | 388 | |
a174a3c5 | 389 | // ======================================================================= |
390 | // function : setupMatrix | |
391 | // purpose : | |
392 | // ======================================================================= | |
60273f77 | 393 | void OpenGl_Text::setupMatrix (const Handle(OpenGl_Context)& theCtx, |
bf5f0ca2 | 394 | const OpenGl_Aspects& theTextAspect, |
395 | const OpenGl_Vec3& theDVec) const | |
a174a3c5 | 396 | { |
a3a3ff3d | 397 | OpenGl_Mat4d aModViewMat, aProjectMat; |
8ed07085 | 398 | if (myText->HasPlane() && myText->HasOwnAnchorPoint()) |
ce01ec26 | 399 | { |
400 | aProjectMat = myProjMatrix * myOrientationMatrix; | |
401 | } | |
402 | else | |
403 | { | |
404 | aProjectMat = myProjMatrix; | |
405 | } | |
c827ea3a | 406 | |
a174a3c5 | 407 | if (myIs2d) |
bf75be98 | 408 | { |
8ed07085 | 409 | const gp_Pnt& aPoint = myText->Position(); |
410 | Graphic3d_TransformUtils::Translate<GLdouble> (aModViewMat, aPoint.X() + theDVec.x(), aPoint.Y() + theDVec.y(), 0.f); | |
825aa485 | 411 | Graphic3d_TransformUtils::Scale<GLdouble> (aModViewMat, 1.f, -1.f, 1.f); |
bf5f0ca2 | 412 | Graphic3d_TransformUtils::Rotate<GLdouble> (aModViewMat, theTextAspect.Aspect()->TextAngle(), 0.f, 0.f, 1.f); |
2166f0fa SK |
413 | } |
414 | else | |
415 | { | |
a3a3ff3d | 416 | OpenGl_Vec3d anObjXYZ; |
417 | OpenGl_Vec3d aWinXYZ = myWinXYZ + OpenGl_Vec3d (theDVec); | |
8ed07085 | 418 | if (!myText->HasPlane() && !theTextAspect.Aspect()->IsTextZoomable()) |
a3a3ff3d | 419 | { |
420 | // Align coordinates to the nearest integer to avoid extra interpolation issues. | |
421 | // Note that for better readability we could also try aligning freely rotated in 3D text (myHasPlane), | |
422 | // when camera orientation co-aligned with horizontal text orientation, | |
423 | // but this might look awkward while rotating camera. | |
424 | aWinXYZ.x() = Floor (aWinXYZ.x()); | |
425 | aWinXYZ.y() = Floor (aWinXYZ.y()); | |
426 | } | |
427 | Graphic3d_TransformUtils::UnProject<Standard_Real> (aWinXYZ.x(), aWinXYZ.y(), aWinXYZ.z(), | |
428 | THE_IDENTITY_MATRIX, aProjectMat, theCtx->Viewport(), | |
429 | anObjXYZ.x(), anObjXYZ.y(), anObjXYZ.z()); | |
825aa485 | 430 | |
8ed07085 | 431 | if (myText->HasPlane()) |
ce01ec26 | 432 | { |
8ed07085 | 433 | const gp_Ax2& anOrientation = myText->Orientation(); |
434 | const gp_Dir& aVectorDir = anOrientation.XDirection(); | |
435 | const gp_Dir& aVectorUp = anOrientation.Direction(); | |
436 | const gp_Dir& aVectorRight = anOrientation.YDirection(); | |
ce01ec26 | 437 | |
ce01ec26 | 438 | aModViewMat.SetColumn (2, OpenGl_Vec3d (aVectorUp.X(), aVectorUp.Y(), aVectorUp.Z())); |
439 | aModViewMat.SetColumn (1, OpenGl_Vec3d (aVectorRight.X(), aVectorRight.Y(), aVectorRight.Z())); | |
440 | aModViewMat.SetColumn (0, OpenGl_Vec3d (aVectorDir.X(), aVectorDir.Y(), aVectorDir.Z())); | |
3f1eb0ab | 441 | |
8ed07085 | 442 | if (!myText->HasOwnAnchorPoint()) |
3f1eb0ab | 443 | { |
444 | OpenGl_Mat4d aPosMat; | |
8ed07085 | 445 | const gp_Pnt& aPoint = myText->Position(); |
446 | aPosMat.SetColumn (3, OpenGl_Vec3d (aPoint.X(), aPoint.Y(), aPoint.Z())); | |
3f1eb0ab | 447 | aPosMat *= aModViewMat; |
448 | aModViewMat.SetColumn (3, aPosMat.GetColumn (3)); | |
449 | } | |
450 | else | |
451 | { | |
a3a3ff3d | 452 | aModViewMat.SetColumn (3, anObjXYZ); |
3f1eb0ab | 453 | } |
ce01ec26 | 454 | } |
455 | else | |
456 | { | |
a3a3ff3d | 457 | Graphic3d_TransformUtils::Translate<GLdouble> (aModViewMat, anObjXYZ.x(), anObjXYZ.y(), anObjXYZ.z()); |
bf5f0ca2 | 458 | Graphic3d_TransformUtils::Rotate<GLdouble> (aModViewMat, theTextAspect.Aspect()->TextAngle(), 0.0, 0.0, 1.0); |
ce01ec26 | 459 | } |
825aa485 | 460 | |
bf5f0ca2 | 461 | if (!theTextAspect.Aspect()->IsTextZoomable()) |
a174a3c5 | 462 | { |
825aa485 | 463 | Graphic3d_TransformUtils::Scale<GLdouble> (aModViewMat, myScaleHeight, myScaleHeight, myScaleHeight); |
a174a3c5 | 464 | } |
56689b27 | 465 | else if (theCtx->HasRenderScale()) |
466 | { | |
467 | Graphic3d_TransformUtils::Scale<GLdouble> (aModViewMat, theCtx->RenderScaleInv(), theCtx->RenderScaleInv(), theCtx->RenderScaleInv()); | |
468 | } | |
a174a3c5 | 469 | } |
c827ea3a | 470 | |
8ed07085 | 471 | if (myText->HasPlane() && !myText->HasOwnAnchorPoint()) |
3f1eb0ab | 472 | { |
473 | OpenGl_Mat4d aCurrentWorldViewMat; | |
474 | aCurrentWorldViewMat.Convert (theCtx->WorldViewState.Current()); | |
475 | theCtx->WorldViewState.SetCurrent<Standard_Real> (aCurrentWorldViewMat * aModViewMat); | |
476 | } | |
477 | else | |
478 | { | |
479 | theCtx->WorldViewState.SetCurrent<Standard_Real> (aModViewMat); | |
480 | } | |
c827ea3a | 481 | theCtx->ApplyWorldViewMatrix(); |
b990e557 | 482 | |
ce01ec26 | 483 | if (!myIs2d) |
484 | { | |
485 | theCtx->ProjectionState.SetCurrent<Standard_Real> (aProjectMat); | |
486 | theCtx->ApplyProjectionMatrix(); | |
487 | } | |
488 | ||
8613985b | 489 | // Upload updated state to shader program |
490 | theCtx->ShaderManager()->PushState (theCtx->ActiveProgram()); | |
a174a3c5 | 491 | } |
492 | ||
493 | // ======================================================================= | |
494 | // function : drawText | |
495 | // purpose : | |
496 | // ======================================================================= | |
60273f77 | 497 | void OpenGl_Text::drawText (const Handle(OpenGl_Context)& theCtx, |
bf5f0ca2 | 498 | const OpenGl_Aspects& theTextAspect) const |
a174a3c5 | 499 | { |
60273f77 | 500 | (void )theTextAspect; |
7d3e64ef | 501 | if (myVertsVbo.Length() != myTextures.Length() |
502 | || myTextures.IsEmpty()) | |
2166f0fa | 503 | { |
7d3e64ef | 504 | return; |
2166f0fa | 505 | } |
7d3e64ef | 506 | |
507 | for (Standard_Integer anIter = 0; anIter < myTextures.Length(); ++anIter) | |
a174a3c5 | 508 | { |
7d3e64ef | 509 | const GLuint aTexId = myTextures.Value (anIter); |
510 | glBindTexture (GL_TEXTURE_2D, aTexId); | |
a174a3c5 | 511 | |
7d3e64ef | 512 | const Handle(OpenGl_VertexBuffer)& aVerts = myVertsVbo.Value (anIter); |
513 | const Handle(OpenGl_VertexBuffer)& aTCrds = myTCrdsVbo.Value (anIter); | |
514 | aVerts->BindAttribute (theCtx, Graphic3d_TOA_POS); | |
515 | aTCrds->BindAttribute (theCtx, Graphic3d_TOA_UV); | |
2166f0fa | 516 | |
7d3e64ef | 517 | glDrawArrays (GL_TRIANGLES, 0, GLsizei(aVerts->GetElemsNb())); |
2166f0fa | 518 | |
b990e557 | 519 | aTCrds->UnbindAttribute (theCtx, Graphic3d_TOA_UV); |
7d3e64ef | 520 | aVerts->UnbindAttribute (theCtx, Graphic3d_TOA_POS); |
a174a3c5 | 521 | } |
7d3e64ef | 522 | glBindTexture (GL_TEXTURE_2D, 0); |
a174a3c5 | 523 | } |
2166f0fa | 524 | |
a174a3c5 | 525 | // ======================================================================= |
526 | // function : FontKey | |
527 | // purpose : | |
528 | // ======================================================================= | |
bf5f0ca2 | 529 | TCollection_AsciiString OpenGl_Text::FontKey (const OpenGl_Aspects& theAspect, |
530 | Standard_Integer theHeight, | |
531 | unsigned int theResolution) | |
a174a3c5 | 532 | { |
bf5f0ca2 | 533 | const Font_FontAspect anAspect = theAspect.Aspect()->TextFontAspect() != Font_FA_Undefined |
534 | ? theAspect.Aspect()->TextFontAspect() | |
b6472664 | 535 | : Font_FA_Regular; |
bf5f0ca2 | 536 | const TCollection_AsciiString& aFont = !theAspect.Aspect()->TextFont().IsNull() ? theAspect.Aspect()->TextFont()->String() : THE_DEFAULT_FONT; |
537 | return aFont | |
a174a3c5 | 538 | + TCollection_AsciiString(":") + Standard_Integer(anAspect) |
4b1c8733 | 539 | + TCollection_AsciiString(":") + Standard_Integer(theResolution) |
a174a3c5 | 540 | + TCollection_AsciiString(":") + theHeight; |
541 | } | |
542 | ||
543 | // ======================================================================= | |
544 | // function : FindFont | |
545 | // purpose : | |
546 | // ======================================================================= | |
547 | Handle(OpenGl_Font) OpenGl_Text::FindFont (const Handle(OpenGl_Context)& theCtx, | |
bf5f0ca2 | 548 | const OpenGl_Aspects& theAspect, |
549 | Standard_Integer theHeight, | |
550 | unsigned int theResolution, | |
551 | const TCollection_AsciiString& theKey) | |
a174a3c5 | 552 | { |
553 | Handle(OpenGl_Font) aFont; | |
554 | if (theHeight < 2) | |
2166f0fa | 555 | { |
a174a3c5 | 556 | return aFont; // invalid parameters |
557 | } | |
2166f0fa | 558 | |
a174a3c5 | 559 | if (!theCtx->GetResource (theKey, aFont)) |
560 | { | |
561 | Handle(Font_FontMgr) aFontMgr = Font_FontMgr::GetInstance(); | |
bf5f0ca2 | 562 | const TCollection_AsciiString& aFontName = !theAspect.Aspect()->TextFont().IsNull() |
563 | ? theAspect.Aspect()->TextFont()->String() | |
564 | : THE_DEFAULT_FONT; | |
565 | Font_FontAspect anAspect = theAspect.Aspect()->TextFontAspect() != Font_FA_Undefined | |
566 | ? theAspect.Aspect()->TextFontAspect() | |
5b377041 | 567 | : Font_FA_Regular; |
1bbd7c79 | 568 | Font_FTFontParams aParams; |
569 | aParams.PointSize = theHeight; | |
570 | aParams.Resolution = theResolution; | |
571 | if (Handle(Font_FTFont) aFontFt = Font_FTFont::FindAndCreate (aFontName, anAspect, aParams, Font_StrictLevel_Any)) | |
2166f0fa | 572 | { |
1bbd7c79 | 573 | aFont = new OpenGl_Font (aFontFt, theKey); |
574 | if (!aFont->Init (theCtx)) | |
65360da3 | 575 | { |
1bbd7c79 | 576 | theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, |
577 | TCollection_AsciiString ("Font '") + aFontName + "' - initialization of GL resources has failed!"); | |
65360da3 | 578 | aFontFt.Nullify(); |
1bbd7c79 | 579 | aFont->Release (theCtx.get()); |
65360da3 | 580 | aFont = new OpenGl_Font (aFontFt, theKey); |
581 | } | |
a174a3c5 | 582 | } |
65360da3 | 583 | else |
a174a3c5 | 584 | { |
1bbd7c79 | 585 | theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, |
586 | TCollection_AsciiString ("Font '") + aFontName + "' is not found in the system!"); | |
65360da3 | 587 | aFont = new OpenGl_Font (aFontFt, theKey); |
a174a3c5 | 588 | } |
a174a3c5 | 589 | |
b34efb62 | 590 | theCtx->ShareResource (theKey, aFont); |
a174a3c5 | 591 | } |
592 | return aFont; | |
593 | } | |
594 | ||
6fe58c66 | 595 | // ======================================================================= |
596 | // function : drawRect | |
597 | // purpose : | |
598 | // ======================================================================= | |
599 | void OpenGl_Text::drawRect (const Handle(OpenGl_Context)& theCtx, | |
bf5f0ca2 | 600 | const OpenGl_Aspects& theTextAspect, |
601 | const OpenGl_Vec4& theColorSubs) const | |
6fe58c66 | 602 | { |
603 | Handle(OpenGl_ShaderProgram) aPrevProgram = theCtx->ActiveProgram(); | |
604 | if (myBndVertsVbo.IsNull()) | |
605 | { | |
606 | OpenGl_Vec2 aQuad[4] = | |
607 | { | |
608 | OpenGl_Vec2(myBndBox.Right, myBndBox.Bottom), | |
609 | OpenGl_Vec2(myBndBox.Right, myBndBox.Top), | |
610 | OpenGl_Vec2(myBndBox.Left, myBndBox.Bottom), | |
611 | OpenGl_Vec2(myBndBox.Left, myBndBox.Top) | |
612 | }; | |
048e1b3b | 613 | if (theCtx->ToUseVbo()) |
614 | { | |
615 | myBndVertsVbo = new OpenGl_VertexBuffer(); | |
616 | } | |
617 | else | |
618 | { | |
619 | myBndVertsVbo = new OpenGl_VertexBufferCompat(); | |
620 | } | |
6fe58c66 | 621 | myBndVertsVbo->Init (theCtx, 2, 4, aQuad[0].GetData()); |
622 | } | |
623 | ||
c40eb6b9 | 624 | // bind unlit program |
625 | theCtx->ShaderManager()->BindFaceProgram (Handle(OpenGl_TextureSet)(), Graphic3d_TOSM_UNLIT, | |
626 | Graphic3d_AlphaMode_Opaque, Standard_False, Standard_False, | |
627 | Handle(OpenGl_ShaderProgram)()); | |
8613985b | 628 | |
6fe58c66 | 629 | #if !defined(GL_ES_VERSION_2_0) |
630 | if (theCtx->core11 != NULL | |
631 | && theCtx->ActiveProgram().IsNull()) | |
632 | { | |
633 | glBindTexture (GL_TEXTURE_2D, 0); | |
634 | } | |
635 | #endif | |
636 | theCtx->SetColor4fv (theColorSubs); | |
8d1a539c | 637 | setupMatrix (theCtx, theTextAspect, OpenGl_Vec3 (0.0f, 0.0f, 0.0f)); |
6fe58c66 | 638 | myBndVertsVbo->BindAttribute (theCtx, Graphic3d_TOA_POS); |
639 | ||
640 | theCtx->core20fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4); | |
641 | ||
642 | myBndVertsVbo->UnbindAttribute (theCtx, Graphic3d_TOA_POS); | |
643 | theCtx->BindProgram (aPrevProgram); | |
644 | } | |
645 | ||
a174a3c5 | 646 | // ======================================================================= |
647 | // function : render | |
648 | // purpose : | |
649 | // ======================================================================= | |
60273f77 | 650 | void OpenGl_Text::render (const Handle(OpenGl_Context)& theCtx, |
bf5f0ca2 | 651 | const OpenGl_Aspects& theTextAspect, |
652 | const OpenGl_Vec4& theColorText, | |
653 | const OpenGl_Vec4& theColorSubs, | |
654 | unsigned int theResolution) const | |
a174a3c5 | 655 | { |
8ed07085 | 656 | if (myText->Text().IsEmpty()) |
a174a3c5 | 657 | { |
658 | return; | |
659 | } | |
660 | ||
4b1c8733 | 661 | // Note that using difference resolution in different Views in same Viewer |
662 | // will lead to performance regression (for example, text will be recreated every time). | |
8ed07085 | 663 | const TCollection_AsciiString aFontKey = FontKey (theTextAspect, (Standard_Integer)myText->Height(), theResolution); |
a174a3c5 | 664 | if (!myFont.IsNull() |
665 | && !myFont->ResourceKey().IsEqual (aFontKey)) | |
666 | { | |
667 | // font changed | |
10b9c7df | 668 | const_cast<OpenGl_Text* > (this)->Release (theCtx.operator->()); |
a174a3c5 | 669 | } |
670 | ||
671 | if (myFont.IsNull()) | |
672 | { | |
8ed07085 | 673 | myFont = FindFont (theCtx, theTextAspect, (Standard_Integer)myText->Height(), theResolution, aFontKey); |
65360da3 | 674 | } |
675 | if (!myFont->WasInitialized()) | |
676 | { | |
677 | return; | |
a174a3c5 | 678 | } |
679 | ||
680 | if (myTextures.IsEmpty()) | |
681 | { | |
317d68c9 | 682 | Font_TextFormatter aFormatter; |
8ed07085 | 683 | |
684 | aFormatter.SetupAlignment (myText->HorizontalAlignment(), myText->VerticalAlignment()); | |
a174a3c5 | 685 | aFormatter.Reset(); |
317d68c9 | 686 | |
8ed07085 | 687 | aFormatter.Append (myText->Text(), *myFont->FTFont()); |
a174a3c5 | 688 | aFormatter.Format(); |
689 | ||
317d68c9 | 690 | OpenGl_TextBuilder aBuilder; |
691 | aBuilder.Perform (aFormatter, | |
692 | theCtx, | |
693 | *myFont.operator->(), | |
694 | myTextures, | |
695 | myVertsVbo, | |
696 | myTCrdsVbo); | |
697 | ||
a174a3c5 | 698 | aFormatter.BndBox (myBndBox); |
6fe58c66 | 699 | if (!myBndVertsVbo.IsNull()) |
700 | { | |
701 | myBndVertsVbo->Release (theCtx.get()); | |
702 | myBndVertsVbo.Nullify(); | |
703 | } | |
a174a3c5 | 704 | } |
705 | ||
706 | if (myTextures.IsEmpty()) | |
707 | { | |
708 | return; | |
709 | } | |
710 | ||
a174a3c5 | 711 | myScaleHeight = 1.0f; |
712 | ||
56689b27 | 713 | theCtx->WorldViewState.Push(); |
c827ea3a | 714 | myModelMatrix.Convert (theCtx->WorldViewState.Current() * theCtx->ModelWorldState.Current()); |
715 | ||
56689b27 | 716 | const GLdouble aPointSize = (GLdouble )myFont->FTFont()->PointSize(); |
a174a3c5 | 717 | if (!myIs2d) |
718 | { | |
8ed07085 | 719 | const gp_Pnt& aPoint = myText->Position(); |
720 | Graphic3d_TransformUtils::Project<Standard_Real> (aPoint.X(), aPoint.Y(), aPoint.Z(), | |
56689b27 | 721 | myModelMatrix, myProjMatrix, theCtx->Viewport(), |
a3a3ff3d | 722 | myWinXYZ.x(), myWinXYZ.y(), myWinXYZ.z()); |
a174a3c5 | 723 | |
724 | // compute scale factor for constant text height | |
8ed07085 | 725 | if (!theTextAspect.Aspect()->IsTextZoomable()) |
56689b27 | 726 | { |
727 | Graphic3d_Vec3d aPnt1, aPnt2; | |
a3a3ff3d | 728 | Graphic3d_TransformUtils::UnProject<Standard_Real> (myWinXYZ.x(), myWinXYZ.y(), myWinXYZ.z(), |
729 | THE_IDENTITY_MATRIX, myProjMatrix, theCtx->Viewport(), | |
56689b27 | 730 | aPnt1.x(), aPnt1.y(), aPnt1.z()); |
a3a3ff3d | 731 | Graphic3d_TransformUtils::UnProject<Standard_Real> (myWinXYZ.x(), myWinXYZ.y() + aPointSize, myWinXYZ.z(), |
732 | THE_IDENTITY_MATRIX, myProjMatrix, theCtx->Viewport(), | |
56689b27 | 733 | aPnt2.x(), aPnt2.y(), aPnt2.z()); |
734 | myScaleHeight = (aPnt2.y() - aPnt1.y()) / aPointSize; | |
a174a3c5 | 735 | } |
736 | } | |
a174a3c5 | 737 | |
b990e557 | 738 | #if !defined(GL_ES_VERSION_2_0) |
dd1ae9df | 739 | if (theCtx->core11 != NULL |
740 | && theCtx->caps->ffpEnable) | |
65360da3 | 741 | { |
742 | glDisable (GL_LIGHTING); | |
743 | } | |
744 | #endif | |
a174a3c5 | 745 | |
746 | // setup depth test | |
8d1a539c | 747 | const bool hasDepthTest = !myIs2d |
bf5f0ca2 | 748 | && theTextAspect.Aspect()->TextStyle() != Aspect_TOST_ANNOTATION; |
8d1a539c | 749 | if (!hasDepthTest) |
a174a3c5 | 750 | { |
751 | glDisable (GL_DEPTH_TEST); | |
752 | } | |
753 | ||
65360da3 | 754 | if (theCtx->core15fwd != NULL) |
a174a3c5 | 755 | { |
65360da3 | 756 | theCtx->core15fwd->glActiveTexture (GL_TEXTURE0); |
a174a3c5 | 757 | } |
65360da3 | 758 | #if !defined(GL_ES_VERSION_2_0) |
a174a3c5 | 759 | // activate texture unit |
65360da3 | 760 | GLint aTexEnvParam = GL_REPLACE; |
761 | if (theCtx->core11 != NULL) | |
a174a3c5 | 762 | { |
65360da3 | 763 | glDisable (GL_TEXTURE_1D); |
764 | glEnable (GL_TEXTURE_2D); | |
765 | glGetTexEnviv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &aTexEnvParam); | |
766 | if (aTexEnvParam != GL_REPLACE) | |
767 | { | |
768 | glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); | |
769 | } | |
a174a3c5 | 770 | } |
65360da3 | 771 | #endif |
772 | ||
773 | // setup blending | |
774 | glEnable (GL_BLEND); | |
775 | glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | |
a174a3c5 | 776 | |
bf5f0ca2 | 777 | // alpha to coverage makes text too thin |
778 | theCtx->SetSampleAlphaToCoverage (false); | |
779 | ||
a174a3c5 | 780 | // extra drawings |
bf5f0ca2 | 781 | switch (theTextAspect.Aspect()->TextDisplayType()) |
a174a3c5 | 782 | { |
2166f0fa | 783 | case Aspect_TODT_BLEND: |
a174a3c5 | 784 | { |
65360da3 | 785 | #if !defined(GL_ES_VERSION_2_0) |
a174a3c5 | 786 | glEnable (GL_COLOR_LOGIC_OP); |
787 | glLogicOp (GL_XOR); | |
65360da3 | 788 | #endif |
2166f0fa | 789 | break; |
a174a3c5 | 790 | } |
2166f0fa SK |
791 | case Aspect_TODT_SUBTITLE: |
792 | { | |
1f44d29a | 793 | BackPolygonOffsetSentry aPolygonOffsetTmp (hasDepthTest ? theCtx.get() : NULL); |
6fe58c66 | 794 | drawRect (theCtx, theTextAspect, theColorSubs); |
2166f0fa SK |
795 | break; |
796 | } | |
2166f0fa | 797 | case Aspect_TODT_DEKALE: |
a174a3c5 | 798 | { |
1f44d29a | 799 | BackPolygonOffsetSentry aPolygonOffsetTmp (hasDepthTest ? theCtx.get() : NULL); |
b6472664 | 800 | theCtx->SetColor4fv (theColorSubs); |
8d1a539c | 801 | setupMatrix (theCtx, theTextAspect, OpenGl_Vec3 (+1.0f, +1.0f, 0.0f)); |
60273f77 | 802 | drawText (theCtx, theTextAspect); |
8d1a539c | 803 | setupMatrix (theCtx, theTextAspect, OpenGl_Vec3 (-1.0f, -1.0f, 0.0f)); |
60273f77 | 804 | drawText (theCtx, theTextAspect); |
8d1a539c | 805 | setupMatrix (theCtx, theTextAspect, OpenGl_Vec3 (-1.0f, +1.0f, 0.0f)); |
60273f77 | 806 | drawText (theCtx, theTextAspect); |
8d1a539c | 807 | setupMatrix (theCtx, theTextAspect, OpenGl_Vec3 (+1.0f, -1.0f, 0.0f)); |
60273f77 | 808 | drawText (theCtx, theTextAspect); |
a174a3c5 | 809 | break; |
810 | } | |
3cbd0a8e | 811 | case Aspect_TODT_SHADOW: |
812 | { | |
1f44d29a | 813 | BackPolygonOffsetSentry aPolygonOffsetTmp (hasDepthTest ? theCtx.get() : NULL); |
3cbd0a8e | 814 | theCtx->SetColor4fv (theColorSubs); |
8d1a539c | 815 | setupMatrix (theCtx, theTextAspect, OpenGl_Vec3 (+1.0f, -1.0f, 0.0f)); |
3cbd0a8e | 816 | drawText (theCtx, theTextAspect); |
817 | break; | |
818 | } | |
a6eb515f | 819 | case Aspect_TODT_DIMENSION: |
a174a3c5 | 820 | case Aspect_TODT_NORMAL: |
821 | { | |
2166f0fa SK |
822 | break; |
823 | } | |
824 | } | |
825 | ||
a174a3c5 | 826 | // main draw call |
b6472664 | 827 | theCtx->SetColor4fv (theColorText); |
60273f77 | 828 | setupMatrix (theCtx, theTextAspect, OpenGl_Vec3 (0.0f, 0.0f, 0.0f)); |
829 | drawText (theCtx, theTextAspect); | |
2166f0fa | 830 | |
ce01ec26 | 831 | if (!myIs2d) |
832 | { | |
833 | theCtx->ProjectionState.SetCurrent<Standard_Real> (myProjMatrix); | |
834 | theCtx->ApplyProjectionMatrix(); | |
835 | } | |
836 | ||
65360da3 | 837 | #if !defined(GL_ES_VERSION_2_0) |
838 | if (theCtx->core11 != NULL) | |
839 | { | |
840 | glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, aTexEnvParam); | |
841 | } | |
842 | #endif | |
543f0db0 | 843 | |
bf5f0ca2 | 844 | if (theTextAspect.Aspect()->TextDisplayType() == Aspect_TODT_DIMENSION) |
543f0db0 | 845 | { |
543f0db0 | 846 | glDisable (GL_BLEND); |
543f0db0 | 847 | if (!myIs2d) |
848 | { | |
849 | glDisable (GL_DEPTH_TEST); | |
850 | } | |
65360da3 | 851 | #if !defined(GL_ES_VERSION_2_0) |
852 | if (theCtx->core11 != NULL) | |
853 | { | |
854 | glDisable (GL_TEXTURE_2D); | |
65360da3 | 855 | } |
856 | #endif | |
f88457e6 | 857 | const bool aColorMaskBack = theCtx->SetColorMask (false); |
543f0db0 | 858 | |
859 | glClear (GL_STENCIL_BUFFER_BIT); | |
860 | glEnable (GL_STENCIL_TEST); | |
861 | glStencilFunc (GL_ALWAYS, 1, 0xFF); | |
862 | glStencilOp (GL_KEEP, GL_KEEP, GL_REPLACE); | |
863 | ||
6fe58c66 | 864 | drawRect (theCtx, theTextAspect, OpenGl_Vec4 (1.0f, 1.0f, 1.0f, 1.0f)); |
543f0db0 | 865 | |
866 | glStencilFunc (GL_ALWAYS, 0, 0xFF); | |
543f0db0 | 867 | |
f88457e6 | 868 | theCtx->SetColorMask (aColorMaskBack); |
543f0db0 | 869 | } |
870 | ||
b34efb62 | 871 | // reset OpenGL state |
872 | glDisable (GL_BLEND); | |
b34efb62 | 873 | glDisable (GL_STENCIL_TEST); |
65360da3 | 874 | #if !defined(GL_ES_VERSION_2_0) |
b34efb62 | 875 | glDisable (GL_COLOR_LOGIC_OP); |
65360da3 | 876 | #endif |
c827ea3a | 877 | |
878 | // model view matrix was modified | |
879 | theCtx->WorldViewState.Pop(); | |
880 | theCtx->ApplyModelViewMatrix(); | |
5e27df78 | 881 | } |
bc73b006 | 882 | |
883 | // ======================================================================= | |
884 | // function : DumpJson | |
885 | // purpose : | |
886 | // ======================================================================= | |
887 | void OpenGl_Text::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const | |
888 | { | |
889 | OCCT_DUMP_CLASS_BEGIN (theOStream, OpenGl_Text) | |
890 | OCCT_DUMP_BASE_CLASS (theOStream, theDepth, OpenGl_Element) | |
891 | ||
892 | OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myTextures.Size()) | |
893 | ||
894 | for (NCollection_Vector<Handle(OpenGl_VertexBuffer)>::Iterator aCrdsIt (myTCrdsVbo); aCrdsIt.More(); aCrdsIt.Next()) | |
895 | { | |
896 | const Handle(OpenGl_VertexBuffer)& aVertexBuffer = aCrdsIt.Value(); | |
897 | OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, aVertexBuffer.get()) | |
898 | } | |
899 | ||
900 | OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myBndBox) | |
901 | } |