MeVisLab Resolution Independence API
SoCoordinateSystemUtils.h
Go to the documentation of this file.
1 /*************************************************************************************
2 **
3 ** Copyright 2021, MeVis Medical Solutions AG
4 **
5 ** The user may use this file in accordance with the license agreement provided with
6 ** the Software or, alternatively, in accordance with the terms contained in a
7 ** written agreement between the user and MeVis Medical Solutions AG.
8 **
9 ** For further information use the contact form at https://www.mevislab.de/contact
10 **
11 **************************************************************************************/
12 
13 #pragma once
14 
15 #include <mlOpenGL.h>
16 #include <Inventor/So.h>
17 #include <mlGL2DFont.h>
18 #include <mlGLHiDPI.h>
19 
20 #include <SoCoordinateSystem.h>
21 
22 namespace
23 {
24  void renderText(const LabelText& labelText);
25  void renderLabel(const Label& label);
26  void glDrawString(const SbVec2f& screenPosition, const LabelText& labelText);
27  void applyLabelOffset(GLfloat& screenX, GLfloat& screenY, const GLfloat& textWidth, const GLfloat& textAscender, const LabelText& labelText);
28  void fillScreenBoundingBox(Label& label);
29 
30  void setupRenderState();
31  void resetRenderState();
32 
33  void setupRasterPositionStateScreen();
34  void resetRasterPositionState();
35 
36  GLfloat getScreenTextWidth(const LabelText& labelText);
37  GLfloat getScreenTextAscender(const LabelText& labelText);
38 
39  SbVec3f getScreenCoordinate(const SbVec3f& worldCoordinate);
40  SbVec4f getColorWithAlpha(const SbColor& color, float alpha) { return SbVec4f(color[0], color[1], color[2], alpha); }
41 
42  void setupRenderState()
43  {
44  glPushMatrix();
45  glPushAttrib(GL_ALL_ATTRIB_BITS);
46  glDisable(GL_LIGHTING);
47 
48  glEnable(GL_BLEND);
49  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
50  glDepthFunc(GL_LEQUAL);
51 
52  glPushAttrib(GL_LINE_BIT);
53  }
54 
55  void resetRenderState()
56  {
57  glPopAttrib();
58 
59  glFlush();
60 
61  glDisable(GL_BLEND);
62 
63  glEnable(GL_LIGHTING);
64  glPopAttrib();
65  glPopMatrix();
66  }
67 
68  void setupRasterPositionStateScreen()
69  {
70  glMatrixMode(GL_MODELVIEW);
71  glPushMatrix();
72  glLoadIdentity();
73  glMatrixMode(GL_PROJECTION);
74 
75  glPushAttrib(GL_ALL_ATTRIB_BITS);
76 
77  glDisable(GL_LIGHTING);
78  glDisable(GL_CULL_FACE);
79 
81 
82  glPushMatrix();
83  glLoadIdentity();
84  GLint viewport[4];
85  glGetIntegerv(GL_VIEWPORT, viewport);
86 
87  glOrtho(0, viewport[2], 0, viewport[3], 0.f, 1.f);
88 
89  glMatrixMode(GL_MODELVIEW);
90 
91  glEnable(GL_BLEND);
92  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
93  }
94 
95  void resetRasterPositionState()
96  {
97  glPopAttrib();
98 
99  glMatrixMode(GL_PROJECTION);
100  glPopMatrix();
101  glMatrixMode(GL_MODELVIEW);
102  glPopMatrix();
103  }
104 
105  void applyLabelOffset(GLfloat& screenX, GLfloat& screenY, const GLfloat& textWidth, const GLfloat& textAscender, const LabelText& labelText)
106  {
107  screenX -= (textWidth * .5f);
108  screenY -= (textAscender * .5f);
109 
110  // only use text height for distance from axis:
111  screenX += (textAscender * labelText.textShiftFactorScreen[0]);
112  screenY += (textAscender * labelText.textShiftFactorScreen[1]);
113  // only left/right-justify if displacement along x-axis is greater than along y-axis
114  if (abs(labelText.textShiftFactorScreen[0]) > abs(labelText.textShiftFactorScreen[1]))
115  {
116  screenX += (textWidth * .5f * sign(labelText.textShiftFactorScreen[0]));
117  }
118  }
119 
120  void renderText(const LabelText& labelText)
121  {
122  glRasterPos3f(labelText.textPosition[0], labelText.textPosition[1], labelText.textPosition[2]);
123 
124  GLboolean isValidPosition;
125  glGetBooleanv(GL_CURRENT_RASTER_POSITION_VALID, &isValidPosition);
126 
127  if (isValidPosition)
128  {
129  GLfloat currentRasterPosition[4];
130  glGetFloatv(GL_CURRENT_RASTER_POSITION, currentRasterPosition);
131  auto screenX = currentRasterPosition[0];
132  auto screenY = currentRasterPosition[1];
133  const auto screenZ = currentRasterPosition[2];
134 
135  setupRasterPositionStateScreen();
136 
137  glTranslatef(0, 0, -screenZ);
138 
139  const auto textWidth = getScreenTextWidth(labelText);
140  const auto textAscender = getScreenTextAscender(labelText);
141 
142  applyLabelOffset(screenX, screenY, textWidth, textAscender, labelText);
143 
144  const SbVec2f screenPosition(screenX, screenY);
145 
146  glDrawString(screenPosition, labelText);
147 
148  resetRasterPositionState();
149  }
150  }
151 
152  void renderLabel(const Label& label)
153  {
154  auto offset = .25f;
155  if (label.isVisible)
156  {
157  offset = .5f;
158  }
159  const auto tickStart = label.tickPosition + label.tickDirection * offset;
160  const auto tickEnd = label.tickPosition - label.tickDirection * offset;
161 
162  const auto tickColor = getColorWithAlpha(label.tickColor, label.tickAlpha);
163  glColor4fv(tickColor.getValue());
164 
165  glBegin(GL_LINE_STRIP);
166  {
167  glVertex3f(tickStart[0], tickStart[1], tickStart[2]);
168  glVertex3f(tickEnd[0], tickEnd[1], tickEnd[2]);
169  }
170  glEnd();
171 
172  if (label.isVisible)
173  {
174  const auto labelText = label.labelText;
175  glRasterPos3f(labelText.textPosition[0], labelText.textPosition[1], labelText.textPosition[2]);
176 
177  GLfloat currentRasterPosition[4];
178  glGetFloatv(GL_CURRENT_RASTER_POSITION, currentRasterPosition);
179  const auto screenZ = currentRasterPosition[2];
180 
181  setupRasterPositionStateScreen();
182 
183  glTranslatef(0, 0, -screenZ);
184 
185  glDrawString(label.screenBoundingBox[0], labelText);
186 
187  resetRasterPositionState();
188  }
189  }
190 
191  void fillScreenBoundingBox(Label& label)
192  {
194 
195  const auto labelText = label.labelText;
196 
197  glRasterPos3f(labelText.textPosition[0], labelText.textPosition[1], labelText.textPosition[2]);
198 
199  GLboolean isValidPosition;
200  glGetBooleanv(GL_CURRENT_RASTER_POSITION_VALID, &isValidPosition);
201 
202  label.isOnScreen = isValidPosition;
203 
204  if (isValidPosition)
205  {
206  GLfloat currentRasterPosition[4];
207  glGetFloatv(GL_CURRENT_RASTER_POSITION, currentRasterPosition);
208  auto screenX = currentRasterPosition[0];
209  auto screenY = currentRasterPosition[1];
210  const auto screenZ = currentRasterPosition[2];
211 
212  setupRasterPositionStateScreen();
213 
214  glTranslatef(0, 0, -screenZ);
215 
216  const auto textWidth = getScreenTextWidth(labelText);
217  const auto textAscender = getScreenTextAscender(labelText);
218 
219  applyLabelOffset(screenX, screenY, textWidth, textAscender, labelText);
220 
221  label.screenBoundingBox[0].setValue(screenX, screenY);
222  label.screenBoundingBox[1].setValue(screenX + textWidth, screenY + textAscender);
223 
224  resetRasterPositionState();
225  }
226  }
227 
228  void glDrawString(const SbVec2f& screenPosition, const LabelText& labelText)
229  {
230  const auto font = ml::GL2DFont::getDefaultSystemFont();
231  const auto textColor = getColorWithAlpha(labelText.textColor, labelText.textAlpha);
232  font->drawString(screenPosition[0], screenPosition[1], labelText.fontSize, textColor.getValue(), labelText.text.c_str(), 0, false, labelText.useTextShadow, labelText.textShadowColor.getValue());
233  }
234 
235  GLfloat getScreenTextWidth(const LabelText& labelText)
236  {
237  const auto font = ml::GL2DFont::getDefaultSystemFont();
238  return static_cast<GLfloat>(font->getStringWidth(labelText.fontSize,labelText.text.c_str()));
239  }
240 
241  GLfloat getScreenTextAscender(const LabelText& labelText)
242  {
243  const auto font = ml::GL2DFont::getDefaultSystemFont();
244  return static_cast<GLfloat>(font->getFontAscender(labelText.fontSize));
245  }
246 
247  SbVec3f getScreenCoordinate(const SbVec3f& worldCoordinate)
248  {
249  GLdouble modelViewMatrix[16];
250  glGetDoublev(GL_MODELVIEW_MATRIX, modelViewMatrix);
251 
252  GLdouble projectionMatrix[16];
253  glGetDoublev(GL_PROJECTION_MATRIX, projectionMatrix);
254 
255  GLint viewport[4];
256  glGetIntegerv(GL_VIEWPORT, viewport);
257 
258  GLdouble screenX, screenY, screenZ;
259  gluProject(worldCoordinate[0], worldCoordinate[1], worldCoordinate[2],
260  modelViewMatrix, projectionMatrix, viewport,
261  &screenX, &screenY, &screenZ);
262 
263  return SbVec3f(static_cast<float>(screenX), static_cast<float>(screenY), static_cast<float>(screenZ));
264  }
265 }
static GL2DFont * getDefaultSystemFont()
Returns the default system font.
static void disableAllClipPlanes()
Disables all clip planes (needs a valid OpenGL context!).
SbVec2f textShiftFactorScreen
std::string text
SbVec3f textPosition
SbColor textShadowColor
float tickAlpha
SbVec3f tickDirection
void initializeScreenBoundingBox()
LabelText labelText
SbColor tickColor
SbVec3f tickPosition
SbVec2f screenBoundingBox[2]