MeVisLab Toolbox Reference
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& axisText);
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 
51  glPushAttrib(GL_LINE_BIT);
52  }
53 
54  void resetRenderState()
55  {
56  glPopAttrib();
57 
58  glFlush();
59 
60  glDisable(GL_BLEND);
61 
62  glEnable(GL_LIGHTING);
63  glPopAttrib();
64  glPopMatrix();
65  }
66 
67  void setupRasterPositionStateScreen()
68  {
69  glMatrixMode(GL_MODELVIEW);
70  glPushMatrix();
71  glLoadIdentity();
72  glMatrixMode(GL_PROJECTION);
73 
74  glPushAttrib(GL_ALL_ATTRIB_BITS);
75 
76  glDisable(GL_LIGHTING);
77  glDisable(GL_CULL_FACE);
78 
79  ml::OpenGL::disableAllClipPlanes();
80 
81  glPushMatrix();
82  glLoadIdentity();
83  GLint viewport[4];
84  glGetIntegerv(GL_VIEWPORT, viewport);
85 
86  glOrtho(0, viewport[2], 0, viewport[3], 0.f, 1.f);
87 
88  glMatrixMode(GL_MODELVIEW);
89 
90  glEnable(GL_BLEND);
91  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
92  }
93 
94  void resetRasterPositionState()
95  {
96  glPopAttrib();
97 
98  glMatrixMode(GL_PROJECTION);
99  glPopMatrix();
100  glMatrixMode(GL_MODELVIEW);
101  glPopMatrix();
102  }
103 
104  void applyLabelOffset(GLfloat& screenX, GLfloat& screenY, const GLfloat& textWidth, const GLfloat& textAscender, const LabelText& labelText)
105  {
106  screenX -= (textWidth * .5f);
107  screenY -= (textAscender * .5f);
108 
109  // only use text height for distance from axis:
110  screenX += (textAscender * labelText.textShiftFactorScreen[0]);
111  screenY += (textAscender * labelText.textShiftFactorScreen[1]);
112  // only left/right-justify if displacement along x-axis is greater than along y-axis
113  if (abs(labelText.textShiftFactorScreen[0]) > abs(labelText.textShiftFactorScreen[1]))
114  {
115  screenX += (textWidth * .5f * sign(labelText.textShiftFactorScreen[0]));
116  }
117  }
118 
119  void renderText(const LabelText& labelText)
120  {
121  glRasterPos3f(labelText.textPosition[0], labelText.textPosition[1], labelText.textPosition[2]);
122 
123  GLboolean isValidPosition;
124  glGetBooleanv(GL_CURRENT_RASTER_POSITION_VALID, &isValidPosition);
125 
126  if (isValidPosition)
127  {
128  GLfloat currentRasterPosition[4];
129  glGetFloatv(GL_CURRENT_RASTER_POSITION, currentRasterPosition);
130  auto screenX = currentRasterPosition[0];
131  auto screenY = currentRasterPosition[1];
132  const auto screenZ = currentRasterPosition[2];
133 
134  setupRasterPositionStateScreen();
135 
136  glTranslatef(0, 0, -screenZ);
137 
138  const auto textWidth = getScreenTextWidth(labelText);
139  const auto textAscender = getScreenTextAscender(labelText);
140 
141  applyLabelOffset(screenX, screenY, textWidth, textAscender, labelText);
142 
143  const SbVec2f screenPosition(screenX, screenY);
144 
145  glDrawString(screenPosition, labelText);
146 
147  resetRasterPositionState();
148  }
149  }
150 
151  void renderLabel(const Label& label)
152  {
153  auto offset = .25f;
154  if (label.isVisible)
155  {
156  offset = .5f;
157  }
158  const auto tickStart = label.tickPosition + label.tickDirection * offset;
159  const auto tickEnd = label.tickPosition - label.tickDirection * offset;
160 
161  const auto tickColor = getColorWithAlpha(label.tickColor, label.tickAlpha);
162  glColor4fv(tickColor.getValue());
163 
164  glBegin(GL_LINE_STRIP);
165  {
166  glVertex3f(tickStart[0], tickStart[1], tickStart[2]);
167  glVertex3f(tickEnd[0], tickEnd[1], tickEnd[2]);
168  }
169  glEnd();
170 
171  if (label.isVisible)
172  {
173  const auto labelText = label.labelText;
174  glRasterPos3f(labelText.textPosition[0], labelText.textPosition[1], labelText.textPosition[2]);
175 
176  GLfloat currentRasterPosition[4];
177  glGetFloatv(GL_CURRENT_RASTER_POSITION, currentRasterPosition);
178  const auto screenZ = currentRasterPosition[2];
179 
180  setupRasterPositionStateScreen();
181 
182  glTranslatef(0, 0, -screenZ);
183 
184  glDrawString(label.screenBoundingBox[0], labelText);
185 
186  resetRasterPositionState();
187  }
188  }
189 
190  void fillScreenBoundingBox(Label& label)
191  {
193 
194  const auto labelText = label.labelText;
195 
196  glRasterPos3f(labelText.textPosition[0], labelText.textPosition[1], labelText.textPosition[2]);
197 
198  GLboolean isValidPosition;
199  glGetBooleanv(GL_CURRENT_RASTER_POSITION_VALID, &isValidPosition);
200 
201  label.isOnScreen = isValidPosition;
202 
203  if (isValidPosition)
204  {
205  GLfloat currentRasterPosition[4];
206  glGetFloatv(GL_CURRENT_RASTER_POSITION, currentRasterPosition);
207  auto screenX = currentRasterPosition[0];
208  auto screenY = currentRasterPosition[1];
209  const auto screenZ = currentRasterPosition[2];
210 
211  setupRasterPositionStateScreen();
212 
213  glTranslatef(0, 0, -screenZ);
214 
215  const auto textWidth = getScreenTextWidth(labelText);
216  const auto textAscender = getScreenTextAscender(labelText);
217 
218  applyLabelOffset(screenX, screenY, textWidth, textAscender, labelText);
219 
220  label.screenBoundingBox[0].setValue(screenX, screenY);
221  label.screenBoundingBox[1].setValue(screenX + textWidth, screenY + textAscender);
222 
223  resetRasterPositionState();
224  }
225  }
226 
227  void glDrawString(const SbVec2f& screenPosition, const LabelText& labelText)
228  {
229  const auto font = ml::GL2DFont::getDefaultSystemFont();
230  const auto textColor = getColorWithAlpha(labelText.textColor, labelText.textAlpha);
231  font->drawString(screenPosition[0], screenPosition[1], labelText.fontSize, textColor.getValue(), labelText.text.c_str(), 0, false, labelText.useTextShadow, labelText.textShadowColor.getValue());
232  }
233 
234  GLfloat getScreenTextWidth(const LabelText& labelText)
235  {
236  const auto font = ml::GL2DFont::getDefaultSystemFont();
237  return static_cast<GLfloat>(font->getStringWidth(labelText.fontSize,labelText.text.c_str(), strlen(labelText.text.c_str())));;
238  }
239 
240  GLfloat getScreenTextAscender(const LabelText& labelText)
241  {
242  const auto font = ml::GL2DFont::getDefaultSystemFont();
243  return static_cast<GLfloat>(font->getFontAscender(labelText.fontSize));
244  }
245 
246  SbVec3f getScreenCoordinate(const SbVec3f& worldCoordinate)
247  {
248  GLdouble modelViewMatrix[16];
249  glGetDoublev(GL_MODELVIEW_MATRIX, modelViewMatrix);
250 
251  GLdouble projectionMatrix[16];
252  glGetDoublev(GL_PROJECTION_MATRIX, projectionMatrix);
253 
254  GLint viewport[4];
255  glGetIntegerv(GL_VIEWPORT, viewport);
256 
257  GLdouble screenX, screenY, screenZ;
258  gluProject(worldCoordinate[0], worldCoordinate[1], worldCoordinate[2],
259  modelViewMatrix, projectionMatrix, viewport,
260  &screenX, &screenY, &screenZ);
261 
262  return SbVec3f(static_cast<float>(screenX), static_cast<float>(screenY), static_cast<float>(screenZ));
263  }
264 }
DT abs(DT val)
SbVec2f textShiftFactorScreen
std::string text
SbVec3f textPosition
SbColor textShadowColor
float tickAlpha
SbVec3f tickDirection
void initializeScreenBoundingBox()
LabelText labelText
SbColor tickColor
SbVec3f tickPosition
SbVec2f screenBoundingBox[2]