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
22namespace
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(), strlen(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()
get the default system font (already initialized, a valid GL context is only required for the draw me...
static void disableAllClipPlanes()
disables all clip planes (needs a valid OpenGL context!)
SbVec2f textShiftFactorScreen
std::string text
SbColor textShadowColor
SbVec3f tickDirection
void initializeScreenBoundingBox()
LabelText labelText
SbColor tickColor
SbVec3f tickPosition
SbVec2f screenBoundingBox[2]