0023022: This is desirable to access OpenGl extensions and core API (1.2+) in one...
[occt.git] / src / OpenGl / OpenGl_GraphicDriver_Layer.cxx
1 // File:      OpenGl_GraphicDriver_Layer.cxx
2 // Created:   20 October 2011
3 // Author:    Sergey ZERCHANINOV
4 // Copyright: OPEN CASCADE 2011
5
6 #include <OpenGl_GlCore11.hxx>
7
8 #include <OpenGl_GraphicDriver.hxx>
9
10 #include <OSD_FontAspect.hxx>
11
12 #include <OpenGl_Display.hxx>
13 #include <OpenGl_AspectText.hxx>
14 #include <OpenGl_TextParam.hxx>
15
16 #include <GL/glu.h>
17
18 /*----------------------------------------------------------------------*/
19
20 struct OpenGl_LAYER_PROP
21 {
22   int        ListId;
23
24   TEL_COLOUR Color;
25   int        NbPoints;
26   int        LineType;
27   float      LineWidth;
28   int        FontCurrent;
29
30   Standard_Boolean FontChanged;
31
32   OpenGl_AspectText AspectText;
33   OpenGl_TextParam TextParam;
34 };
35
36 /*----------------------------------------------------------------------*/
37
38 static const TEL_COLOUR myDefaultColor = {{ 1.F, 1.F, 1.F, 1.F }};
39 static const CALL_DEF_CONTEXTTEXT myDefaultContextText =
40 {
41   1, //IsDef
42   1, //IsSet
43   "Courier", //Font
44   0.3F, //Space
45   1.F, //Expan
46   { 1.F, 1.F, 1.F }, //Color
47   (int)Aspect_TOST_NORMAL, //Style
48   (int)Aspect_TODT_NORMAL, //DisplayType
49   { 1.F, 1.F, 1.F }, //ColorSubTitle
50   0, //TextZoomable
51   0.F, //TextAngle
52   (int)OSD_FA_Regular //TextFontAspect
53 };
54
55 static Standard_Boolean TheLayerIsOpen = Standard_False;
56 static OpenGl_LAYER_PROP TheLayerProp;
57
58 /*----------------------------------------------------------------------*/
59
60 void InitLayerProp (const int AListId)
61 {
62   TheLayerProp.ListId = AListId;
63
64   if (AListId)
65   {
66     TheLayerProp.Color = myDefaultColor;
67     TheLayerProp.NbPoints = 0;
68     TheLayerProp.LineType = -1;
69     TheLayerProp.LineWidth = -1.F;
70     TheLayerProp.FontCurrent = 0;
71
72     TheLayerProp.FontChanged = Standard_False;
73
74     TheLayerProp.AspectText.SetContext(myDefaultContextText);
75
76     TheLayerProp.TextParam.Height = -1;
77     TheLayerProp.TextParam.HAlign = Graphic3d_HTA_LEFT;
78     TheLayerProp.TextParam.VAlign = Graphic3d_VTA_BOTTOM;
79   }
80 }
81
82 /*----------------------------------------------------------------------*/
83
84 void OpenGl_GraphicDriver::Layer (Aspect_CLayer2d& ACLayer)
85 {
86   ACLayer.ptrLayer = (call_def_ptrLayer) malloc (sizeof (CALL_DEF_PTRLAYER));
87   ACLayer.ptrLayer->listIndex = glGenLists(1);
88 }
89
90 /*----------------------------------------------------------------------*/
91
92 void OpenGl_GraphicDriver::RemoveLayer (const Aspect_CLayer2d& ACLayer)
93 {
94   if (!ACLayer.ptrLayer) return;
95   if (!ACLayer.ptrLayer->listIndex) return;
96   if (TheLayerProp.ListId == ACLayer.ptrLayer->listIndex)
97     EndLayer();
98   glDeleteLists (ACLayer.ptrLayer->listIndex, 1);
99   ACLayer.ptrLayer->listIndex = 0;
100   //szvgl: memory leak here?
101   //free ( ACLayer.ptrLayer );
102   //ACLayer.ptrLayer = NULL;
103 }
104
105 /*----------------------------------------------------------------------*/
106
107 void OpenGl_GraphicDriver::BeginLayer (const Aspect_CLayer2d& ACLayer)
108 {
109   call_def_ptrLayer ptrLayer = (call_def_ptrLayer) ACLayer.ptrLayer;
110   if (!ptrLayer) return;
111
112   InitLayerProp(ptrLayer->listIndex);
113   if (!TheLayerProp.ListId) return;
114
115   glEnable(GL_TEXTURE_2D);
116   //GLboolean stat = glIsEnabled( GL_TEXTURE_2D );
117
118   glNewList (TheLayerProp.ListId, GL_COMPILE);
119   TheLayerIsOpen = Standard_True;
120 }
121
122 void OpenGl_GraphicDriver::BeginPolygon2d ()
123 {
124   if (!TheLayerProp.ListId) return;
125   TheLayerProp.NbPoints = 0;
126   glBegin (GL_POLYGON);
127 }
128
129 void OpenGl_GraphicDriver::BeginPolyline2d ()
130 {
131   if (!TheLayerProp.ListId) return;
132   TheLayerProp.NbPoints = 0;
133   glBegin (GL_LINE_STRIP);
134 }
135
136 void OpenGl_GraphicDriver::ClearLayer (const Aspect_CLayer2d& ACLayer)
137 {
138   if (!ACLayer.ptrLayer) return;
139
140   InitLayerProp(ACLayer.ptrLayer->listIndex);
141   if (!TheLayerProp.ListId) return;
142
143   glNewList (TheLayerProp.ListId, GL_COMPILE);
144   glEndList ();
145 }
146
147 void OpenGl_GraphicDriver::Draw (const Standard_ShortReal X, const Standard_ShortReal Y)
148 {
149   if (!TheLayerProp.ListId) return;
150   TheLayerProp.NbPoints++;
151   glVertex3f (X, Y, 0.F);
152 }
153
154 void OpenGl_GraphicDriver::Edge (const Standard_ShortReal X, const Standard_ShortReal Y)
155 {
156   if (!TheLayerProp.ListId) return;
157   TheLayerProp.NbPoints++;
158   glVertex3f (X, Y, 0.F);
159 }
160
161 void OpenGl_GraphicDriver::EndLayer ()
162 {
163   if (!TheLayerProp.ListId) return;
164   if (TheLayerIsOpen)
165   {
166     glEndList();
167     TheLayerIsOpen = Standard_False;
168   }
169   TheLayerProp.ListId = 0;
170 }
171
172 void OpenGl_GraphicDriver::EndPolygon2d ()
173 {
174   if (!TheLayerProp.ListId) return;
175   glEnd ();
176 }
177
178 void OpenGl_GraphicDriver::EndPolyline2d ()
179 {
180   if (!TheLayerProp.ListId) return;
181   glEnd ();
182 }
183
184 void OpenGl_GraphicDriver::Move (const Standard_ShortReal X, const Standard_ShortReal Y)
185 {
186   if (!TheLayerProp.ListId) return;
187   if (TheLayerProp.NbPoints)
188   {
189     glEnd ();
190     TheLayerProp.NbPoints = 0;
191     glBegin (GL_LINE_STRIP);
192   }
193   TheLayerProp.NbPoints++;
194   glVertex3f (X, Y, 0.F);
195 }
196
197 void OpenGl_GraphicDriver::Rectangle (const Standard_ShortReal X, const Standard_ShortReal Y, const Standard_ShortReal Width, const Standard_ShortReal Height)
198 {
199   if (!TheLayerProp.ListId) return;
200   glRectf (X, Y, X + Width, Y + Height);
201 }
202
203 void OpenGl_GraphicDriver::SetColor (const Standard_ShortReal R, const Standard_ShortReal G, const Standard_ShortReal B)
204 {
205   if (!TheLayerProp.ListId) return;
206   TheLayerProp.Color.rgb[0] = R;
207   TheLayerProp.Color.rgb[1] = G;
208   TheLayerProp.Color.rgb[2] = B;
209   glColor3fv (TheLayerProp.Color.rgb);
210 }
211
212 void OpenGl_GraphicDriver::SetTransparency (const Standard_ShortReal ATransparency)
213 {
214   if (!TheLayerProp.ListId) return;
215   TheLayerProp.Color.rgb[3] = ATransparency;
216   glEnable (GL_BLEND);
217   glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
218   glColor4fv (TheLayerProp.Color.rgb);
219 }
220
221 void OpenGl_GraphicDriver::UnsetTransparency ()
222 {
223   if (!TheLayerProp.ListId) return;
224   TheLayerProp.Color.rgb[3] = 1.F;
225   glDisable (GL_BLEND);
226 }
227
228 void OpenGl_GraphicDriver::SetLineAttributes (const Standard_Integer Type, const Standard_ShortReal Width)
229 {
230   if (!TheLayerProp.ListId || openglDisplay.IsNull()) return;
231
232   if (TheLayerProp.LineType != Type)
233   {
234     TheLayerProp.LineType = Type;
235     openglDisplay->SetTypeOfLine((Aspect_TypeOfLine) Type);
236   }
237   if (TheLayerProp.LineWidth != Width)
238   {
239     TheLayerProp.LineWidth = Width;
240     glLineWidth ((GLfloat) Width);
241   }
242 }
243
244 void OpenGl_GraphicDriver::SetTextAttributes (const Standard_CString Font, const Standard_Integer AType, const Standard_ShortReal R, const Standard_ShortReal G, const Standard_ShortReal B)
245 {
246   if (!TheLayerProp.ListId || openglDisplay.IsNull()) return;
247
248   // get current subtitle text color
249   const TEL_COLOUR &aSubColor = TheLayerProp.AspectText.SubtitleColor ();
250
251   // update if there are any modifications
252   if (strcmp (TheLayerProp.AspectText.Font(), Font) != 0   ||
253       (int)TheLayerProp.AspectText.DisplayType() != AType  ||
254       aSubColor.rgb[0] != (float)R || 
255       aSubColor.rgb[1] != (float)G ||
256       aSubColor.rgb[2] != (float)B)
257   {
258     CALL_DEF_CONTEXTTEXT aContextText = myDefaultContextText;
259
260     aContextText.Font = Font;
261     aContextText.DisplayType = AType;
262     aContextText.ColorSubTitle.r = R;
263     aContextText.ColorSubTitle.g = G;
264     aContextText.ColorSubTitle.b = B;
265     TheLayerProp.AspectText.SetContext(aContextText);
266     TheLayerProp.FontChanged = Standard_True;
267   }
268 }
269
270 void OpenGl_GraphicDriver::Text (const Standard_CString AText, const Standard_ShortReal X, const Standard_ShortReal Y, const Standard_ShortReal AHeight)
271 {
272   if (!TheLayerProp.ListId || openglDisplay.IsNull()) return;
273
274   const Standard_ShortReal height = (AHeight < 0)? DefaultTextHeight() : AHeight;
275
276   if ( TheLayerProp.TextParam.Height != height || TheLayerProp.FontChanged || TheLayerProp.FontCurrent == 0 )
277   {
278     TheLayerProp.TextParam.Height = (int )height;
279     TheLayerProp.FontCurrent = openglDisplay->FindFont(TheLayerProp.AspectText.Font(), TheLayerProp.AspectText.FontAspect(), (int )height);
280     TheLayerProp.FontChanged = Standard_False;
281   }
282
283   TCollection_ExtendedString aExtStr(AText);
284   const Techar *aTChStr = (const Techar *)aExtStr.ToExtString();
285
286   //szv: conversion of Techar to wchar_t
287   wchar_t *aWChStr = (wchar_t*)aTChStr;
288   if (sizeof(Techar) != sizeof(wchar_t))
289   {
290     Tint i = 0; while (aTChStr[i++]);
291     aWChStr = new wchar_t[i];
292     i = 0; while (aWChStr[i++] = (wchar_t)(*aTChStr++));
293   }
294
295   const Aspect_TypeOfDisplayText aDispType =
296     TheLayerProp.AspectText.DisplayType();
297
298   // display type of text
299   if (aDispType != Aspect_TODT_NORMAL)
300   {
301     switch (aDispType)
302     {
303       // blend type
304       case Aspect_TODT_BLEND:
305       {
306         glEnable(GL_COLOR_LOGIC_OP);
307         glLogicOp(GL_XOR);
308       }
309       break;
310       
311       // subtitle type
312       case Aspect_TODT_SUBTITLE:
313       {
314         GLint aViewport[4];
315         GLdouble aModelMatrix[16], aProjMatrix[16];
316         glGetIntegerv (GL_VIEWPORT, aViewport);
317         glGetDoublev (GL_MODELVIEW_MATRIX, aModelMatrix);
318         glGetDoublev (GL_PROJECTION_MATRIX, aProjMatrix);
319
320         int aWidth, anAscent, aDescent;
321         openglDisplay->StringSize(aWChStr, aWidth, anAscent, aDescent);
322
323         GLdouble aWinX, aWinY, aWinZ;
324         gluProject ((GLdouble)X, (GLdouble)Y, 0.0, aModelMatrix,
325           aProjMatrix, aViewport, &aWinX, &aWinY, &aWinZ);
326
327         // project coordinates
328         GLdouble aCoordX[4];
329         GLdouble aCoordY[4];
330         GLdouble aCoordZ[4];
331
332         // left bottom corner
333         gluUnProject (aWinX,  aWinY + aDescent, aWinZ, aModelMatrix,
334           aProjMatrix, aViewport, &aCoordX[0], &aCoordY[0], &aCoordZ[0]);
335
336         // right bottom corner        
337         gluUnProject (aWinX + aWidth, aWinY + aDescent, aWinZ, aModelMatrix,
338           aProjMatrix, aViewport, &aCoordX[1], &aCoordY[1], &aCoordZ[1]);
339
340         // right top corner
341         gluUnProject (aWinX + aWidth, aWinY + anAscent, aWinZ, aModelMatrix,
342           aProjMatrix, aViewport, &aCoordX[2], &aCoordY[2], &aCoordZ[2]);
343
344         // left top corner
345         gluUnProject (aWinX, aWinY + anAscent, aWinZ, aModelMatrix, 
346           aProjMatrix, aViewport, &aCoordX[3], &aCoordY[3], &aCoordZ[3]);
347
348         // draw colored plane and reset the color
349         glColor3fv (TheLayerProp.AspectText.SubtitleColor ().rgb);
350         glBegin(GL_POLYGON);
351         glVertex3d(aCoordX[0], aCoordY[0], aCoordZ[0]);
352         glVertex3d(aCoordX[1], aCoordY[1], aCoordZ[1]);
353         glVertex3d(aCoordX[2], aCoordY[2], aCoordZ[2]);
354         glVertex3d(aCoordX[3], aCoordY[3], aCoordZ[3]);
355         glEnd();
356         glColor3fv (TheLayerProp.Color.rgb);
357       }
358       break;
359
360       case Aspect_TODT_DEKALE:
361       {
362         GLint aViewport[4];
363         GLdouble aModelMatrix[16], aProjMatrix[16];
364         glGetIntegerv (GL_VIEWPORT, aViewport);
365         glGetDoublev (GL_MODELVIEW_MATRIX, aModelMatrix);
366         glGetDoublev (GL_PROJECTION_MATRIX, aProjMatrix);
367
368         GLdouble aWinX, aWinY, aWinZ;
369         gluProject ((GLdouble)X, (GLdouble)Y, 0.0, aModelMatrix,
370           aProjMatrix, aViewport, &aWinX, &aWinY, &aWinZ);
371
372         GLdouble aProjX, aProjY, aProjZ;
373
374         gluUnProject (aWinX + 1, aWinY + 1, aWinZ, aModelMatrix,
375           aProjMatrix, aViewport, &aProjX, &aProjY, &aProjZ);
376
377         // draw a decal
378         glColor3fv (TheLayerProp.AspectText.SubtitleColor ().rgb);
379         openglDisplay->RenderText (aWChStr, 1, (float)aProjX, (float)aProjY,
380           (float)aProjZ, &TheLayerProp.AspectText, &TheLayerProp.TextParam);
381
382         gluUnProject (aWinX, aWinY, aWinZ, aModelMatrix, aProjMatrix,
383           aViewport, &aProjX, &aProjY, &aProjZ);
384
385         gluUnProject (aWinX - 1, aWinY - 1, aWinZ, aModelMatrix, aProjMatrix, 
386           aViewport, &aProjX, &aProjY, &aProjZ);
387
388         openglDisplay->RenderText(aWChStr, 1, (float)aProjX, (float)aProjY,
389           (float)aProjZ, &TheLayerProp.AspectText, &TheLayerProp.TextParam);
390
391         gluUnProject (aWinX - 1, aWinY + 1, aWinZ, aModelMatrix, aProjMatrix, 
392           aViewport, &aProjX, &aProjY, &aProjZ);
393
394         openglDisplay->RenderText(aWChStr, 1, (float)aProjX, (float)aProjY,
395           (float)aProjZ, &TheLayerProp.AspectText, &TheLayerProp.TextParam);
396
397         gluUnProject (aWinX + 1, aWinY - 1, aWinZ, aModelMatrix, aProjMatrix,
398           aViewport, &aProjX, &aProjY, &aProjZ);
399
400         openglDisplay->RenderText(aWChStr, 1, (float)aProjX, (float)aProjY,
401           (float)aProjZ, &TheLayerProp.AspectText, &TheLayerProp.TextParam);
402         glColor3fv (TheLayerProp.Color.rgb);
403       }
404       break;
405     }
406   }
407
408   openglDisplay->RenderText(aWChStr, 1, (float)X, (float)Y, 0.F,
409     &TheLayerProp.AspectText, &TheLayerProp.TextParam);
410
411   if (aDispType == Aspect_TODT_BLEND)
412     glDisable(GL_COLOR_LOGIC_OP);
413
414   //szv: delete temporary wide string
415   if (sizeof(Techar) != sizeof(wchar_t))
416     delete[] aWChStr;
417 }
418
419 void OpenGl_GraphicDriver::TextSize (const Standard_CString AText, const Standard_ShortReal AHeight, Standard_ShortReal& AWidth, Standard_ShortReal& AnAscent, Standard_ShortReal& ADescent) const
420 {
421   if (!TheLayerProp.ListId || openglDisplay.IsNull()) return;
422
423   const Standard_ShortReal height = (AHeight < 0)? DefaultTextHeight() : AHeight;
424
425   if ( TheLayerProp.TextParam.Height != height || TheLayerProp.FontChanged || TheLayerProp.FontCurrent == 0 )
426   {
427     TheLayerProp.TextParam.Height = (int )height;
428     TheLayerProp.FontCurrent = openglDisplay->FindFont(TheLayerProp.AspectText.Font(), TheLayerProp.AspectText.FontAspect(), (int )height);
429     TheLayerProp.FontChanged = Standard_False;
430   }
431
432   TCollection_ExtendedString estr(AText);
433   const Techar *s = (const Techar *)estr.ToExtString();
434
435   //szv: conversion of Techar to wchar_t
436   wchar_t *s1 = (wchar_t*)s;
437   if (sizeof(Techar) != sizeof(wchar_t))
438   {
439     Tint i = 0; while (s[i++]);
440     s1 = new wchar_t[i];
441     i = 0; while (s1[i++] = (wchar_t)(*s++));
442   }
443
444   int aWidth = 0, anAscent = 0, aDescent = 0;
445   openglDisplay->StringSize(s1, aWidth, anAscent, aDescent);
446
447   //szv: delete temporary wide string
448   if (sizeof(Techar) != sizeof(wchar_t))
449     delete[] s1;
450
451   AWidth = (Standard_ShortReal) aWidth;
452   AnAscent = (Standard_ShortReal) anAscent;
453   ADescent = (Standard_ShortReal) aDescent;
454 }