direcs  2012-09-30
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
QtGLContext.cpp
Go to the documentation of this file.
1 /*************************************************************************
2  * Copyright (C) Markus Knapp *
3  * www.direcs.de *
4  * *
5  * This file is part of direcs. *
6  * *
7  * direcs is free software: you can redistribute it and/or modify it *
8  * under the terms of the GNU General Public License as published *
9  * by the Free Software Foundation, version 3 of the License. *
10  * *
11  * direcs is distributed in the hope that it will be useful, *
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14  * GNU General Public License for more details. *
15  * *
16  * You should have received a copy of the GNU General Public License *
17  * along with direcs. If not, see <http://www.gnu.org/licenses/>. *
18  * *
19  *************************************************************************/
20 
21 #include "QtGLContext.h"
22 #include <QMessageBox>
23 
24 QtGLContext::QtGLContext(QWidget* parent /*= 0*/, const QGLWidget* sharedWidget /*= 0*/, Qt::WFlags f /*= 0*/) : QGLWidget(parent, sharedWidget, f), m_imgP(0), m_mousePressed(false)
25 {
26  // first init
27  m_mirrored = false;
28  m_width = 0;
29  m_height = 0;
30  m_pixeldepth = 0;
31 }
32 
33 
35 {
36  //delete[] textureGL;
37  glDeleteTextures(1, &m_texNameGL);
38 }
39 
40 
42 {
43  // INIT
44  // Let OpenGL clear to black
45  glColor3f(0.0,0.0,0.0);
46  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
47 
48  // Set the shading model
49  glShadeModel(GL_FLAT);
50 
51  glMatrixMode(GL_PROJECTION);
52  glLoadIdentity();
53  glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
54  glMatrixMode(GL_MODELVIEW);
55  glLoadIdentity();
56  glGenTextures(1, &m_texNameGL);
57 }
58 
59 
61  {
62  // PAINT
63  glColor3f(1.0,1.0,1.0);
64  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
65 
66  if (!m_imgP)
67  return;
68 
69  glDisable(GL_DEPTH_TEST);
71  glEnable(GL_DEPTH_TEST);
72 
73  if (!m_exit.isNull())
74  {
75  glBegin(GL_LINE_STRIP);
76  glVertex2f(m_entry.x(), m_entry.y());
77  glVertex2f(m_entry.x(), m_exit.y());
78  glVertex2f(m_exit.x(), m_exit.y());
79  glVertex2f(m_exit.x(), m_entry.y());
80  glVertex2f(m_entry.x(), m_entry.y());
81  glEnd();
82  }
83 }
84 
85 
86 void QtGLContext::drawTexture(float ulX, float ulY, float lrX, float lrY)
87 {
88  glEnable(GL_TEXTURE_2D);
89  glBindTexture(GL_TEXTURE_2D, m_texNameGL);
90 
91  switch (m_pixeldepth)
92  {
93  case 8:
94  glTexSubImage2D ( GL_TEXTURE_2D, 0, m_texWidth-m_width, m_texHeight-m_height, m_width, m_height, GL_LUMINANCE, GL_UNSIGNED_BYTE, m_imgP);
95  break;
96  case 24:
97  glTexSubImage2D ( GL_TEXTURE_2D, 0, m_texWidth-m_width, m_texHeight-m_height, m_width, m_height, GL_BGR_EXT, GL_UNSIGNED_BYTE, m_imgP);
98  break;
99  case 32:
100  glTexSubImage2D ( GL_TEXTURE_2D, 0, m_texWidth-m_width, m_texHeight-m_height, m_width, m_height, GL_BGRA_EXT, GL_UNSIGNED_BYTE, m_imgP);
101  break;
102  }
103 
104  // Reset The Modelview Matrix
105  glLoadIdentity();
106  glBegin(GL_QUADS);
107 
108  if (m_flipped)
109  {
110  //flipped vertically
111  glTexCoord2f(ulX, ulY); glVertex2f( -1, -1 );
112  glTexCoord2f(ulX, lrY); glVertex2f( -1, 1 );
113  glTexCoord2f(lrX, lrY); glVertex2f( 1, 1 );
114  glTexCoord2f(lrX, ulY); glVertex2f( 1, -1 );
115  }
116  else
117  {
118  glTexCoord2f(ulX, ulY); glVertex2f( -1, 1 );
119  glTexCoord2f(ulX, lrY); glVertex2f( -1, -1 );
120  glTexCoord2f(lrX, lrY); glVertex2f( 1, -1 );
121  glTexCoord2f(lrX, ulY); glVertex2f( 1, 1 );
122  }
123 
124  if (m_mirrored)
125  {
126  //flipped horicontally
127  glTexCoord2f(ulX, ulY); glVertex2f( 1, 1 );
128  glTexCoord2f(ulX, lrY); glVertex2f( 1, -1 );
129  glTexCoord2f(lrX, lrY); glVertex2f( -1, -1 );
130  glTexCoord2f(lrX, ulY); glVertex2f( -1, 1 );
131  }
132  else
133  {
134  glTexCoord2f(ulX, ulY); glVertex2f( -1, 1 );
135  glTexCoord2f(ulX, lrY); glVertex2f( -1, -1 );
136  glTexCoord2f(lrX, lrY); glVertex2f( 1, -1 );
137  glTexCoord2f(lrX, ulY); glVertex2f( 1, 1 );
138  }
139 
140  glEnd();
141  glDisable(GL_TEXTURE_2D);
142 
143  glTranslatef(-1.0,1.0,0);
144  glScalef(2.0/m_width, 2.0/m_height, 0.0);
145 }
146 
147 
148 
149 unsigned int QtGLContext::NextLargerPowerOfTwo(unsigned int n) {
150  unsigned int candidate = n;
151 
152  while((candidate & (candidate - 1)) != 0) {
153  ++candidate;
154  }
155  return candidate;
156 }
157 
158 
159 /*
160 void QtGLContext::mousePressEvent ( QMouseEvent * event )
161 {
162  // remember the current mouse position
163  if (!m_imgP)
164  return;
165  float scale = static_cast<float>(m_width)/static_cast<float>(this->width());
166  m_entry.setX(event->pos().x()*scale);
167  scale = static_cast<float>(m_height)/ static_cast<float>(this->height());
168  m_entry.setY(-event->pos().y()*scale);
169  m_exit = QPoint(0,0);
170  m_mousePressed = true;
171  this->updateGL();
172 
173  emit saveImage();
174 }
175 
176 
177 void QtGLContext::mouseReleaseEvent(QMouseEvent* event)
178 {
179  if (!m_imgP || !m_mousePressed)
180  return;
181  float scale = static_cast<float>(m_width)/static_cast<float>(this->width());
182  m_exit.setX(event->pos().x()*scale);
183  scale = static_cast<float>(m_height)/ static_cast<float>(this->height());
184  m_exit.setY(-event->pos().y()*scale);
185  int minx, maxx, miny, maxy;
186  if (m_entry.x() == m_exit.x() || m_entry.y() == m_exit.y())
187  return;
188  if (m_entry.x() < m_exit.x())
189  {
190  minx = m_entry.x();
191  maxx = m_exit.x();
192  }
193  else
194  {
195  minx = m_exit.x();
196  maxx = m_entry.x();
197  }
198  if (-m_entry.y() < -m_exit.y())
199  {
200  miny = -m_entry.y();
201  maxy = -m_exit.y();
202  }
203  else
204  {
205  miny = -m_exit.y();
206  maxy = -m_entry.y();
207  }
208  if (maxy >= m_height) maxy = m_height-1;
209  if (maxx >= m_width) maxx = m_width-1;
210  if (miny < 0) miny = 0;
211  if (minx < 0) minx = 0;
212  emit boxCreated(minx, miny, maxx, maxy);
213  m_mousePressed = false;
214  this->updateGL();
215 }
216 
217 void QtGLContext::mouseMoveEvent(QMouseEvent* event)
218 {
219  if (!m_imgP || !m_mousePressed)
220  return;
221  float scale = static_cast<float>(m_width)/static_cast<float>(this->width());
222  m_exit.setX(event->pos().x()*scale);
223  scale = static_cast<float>(m_height)/ static_cast<float>(this->height());
224  m_exit.setY(-event->pos().y()*scale);
225  this->updateGL();
226 }
227 */
228 
229 
230 void QtGLContext::resizeGL(int w, int h)
231 {
232  // RESIZE
233  glViewport(0, 0, (GLsizei) w, (GLsizei) h);
234 }
235 
236 
237 bool QtGLContext::setImage(unsigned char* imgP, const bool flipped) /*flipped=false*/
238 //bool QtGLContext::setImage(unsigned char* imgP, const int width, const int height, const int pixeldepth, const bool flipped) /*flipped=false*/
239 {
240  m_imgP = imgP;
241  /*
242  m_width = width;
243  m_height = height;
244  m_pixeldepth = pixeldepth;
245  */
246  m_flipped = flipped;
247 
248  this->updateGL();
249 
250  // only 8, 24 and 32 bit images are supported
251  if (!imgP || (m_pixeldepth!=8 && m_pixeldepth!=24 && m_pixeldepth!=32))
252  return false;
253 
254  // Enable Texture Mapping
255  glEnable(GL_TEXTURE_2D);
256 
257  // calculate texture size
258  // create texture memory -> put to constructor!
259  // calculate texture coordinates for image
260  // -> now in setImageData
261 
262  // tell OpenGL which texture "id" we will be working with.:
263  glBindTexture(GL_TEXTURE_2D, m_texNameGL);
264  // tell OpenGL that the pixel data which is going to be passed to it is aligned in byte order:
265  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
266 
267  // set the various parameters for the current OpenGL texture:
268  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
269  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
270  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
271  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
272 
273  // tell OpenGL how the texture will act when it is rendered into a scene:
274  // The GL_MODULATE attribute allows you to apply effects such as lighting
275  // and coloring to your texture. If you do not want lighting and coloring to effect
276  // your texture and you would like to display the texture unchanged when coloring
277  // is applied replace GL_MODULATE with GL_DECAL
278  //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
279  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
280 
281  switch(m_pixeldepth)
282  {
283  case 8:
284  glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, m_texWidth, m_texHeight, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, textureGL);
285  break;
286  case 24:
287  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_texWidth,m_texHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, textureGL);
288  break;
289  case 32:
290  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_texWidth,m_texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureGL);
291  break;
292  default:
293  glDisable(GL_TEXTURE_2D);
294  return false;
295  }
296 
297  glDisable(GL_TEXTURE_2D);
298  //resetBox();
299  return true;
300 }
301 
302 
304 {
305  if (state == Qt::Checked)
306  {
307  m_mirrored = true;
308  }
309  else
310  {
311  m_mirrored = false;
312  }
313 }
314 
315 
316 void QtGLContext::setImageData(const int width, const int height, const int pixeldepth)
317 {
318  static bool firstInit = true;
319 
320 
321  m_width = width;
322  m_height = height;
323  m_pixeldepth = pixeldepth;
324 
325  // only the first time
326  if (firstInit)
327  {
328  firstInit=false;
329 
330  // calculate texture size
333 
334  // create texture memory -> put to constructor!
335  textureGL = new GLubyte[m_texHeight*m_texWidth* (m_pixeldepth>>3)];
336 
337  // calculate texture coordinates for image
338  m_texUpperLeftX = float (m_texWidth-m_width) / (float) (m_texWidth);
339  m_texUpperLeftY = float (m_texHeight-m_height) / (float) (m_texHeight);
340  m_texLowerRightX = 1.0; // (float) (_texWidth) / (float) _height;
341  m_texLowerRightY = 1.0; // (float) (_texHeight) / (float) _width;
342  }
343 }