OpenGLCanvas.cpp
Go to the documentation of this file.00001 /**<!--------------------------------------------------------------------> 00002 @file OpenGLCanvas.cpp 00003 @author Travis Fischer (fisch0920@gmail.com) 00004 @author Matthew Jacobs (jacobs.mh@gmail.com) 00005 @date Fall 2008 00006 00007 @brief 00008 Provides an OpenGL rendering view 00009 <!-------------------------------------------------------------------->**/ 00010 00011 #include "OpenGLCanvas.h" 00012 #include "Gui.h" 00013 00014 #include <milton.h> 00015 #include <QtGui> 00016 00017 OpenGLCanvas::OpenGLCanvas(bool defaultInteractionListeners, 00018 Gui *gui, unsigned width, unsigned height) 00019 : QGLWidget(QGLFormat(QGL::SampleBuffers)), Canvas(gui, width, height), m_drawMode(MODE_SOLID) 00020 { 00021 _init(defaultInteractionListeners); 00022 } 00023 00024 OpenGLCanvas::OpenGLCanvas(Gui *gui, unsigned width, unsigned height) 00025 : QGLWidget(QGLFormat(QGL::SampleBuffers)), Canvas(gui, width, height), m_drawMode(MODE_SOLID) 00026 { 00027 _init(true); 00028 } 00029 00030 OpenGLCanvas::~OpenGLCanvas() 00031 { } 00032 00033 void OpenGLCanvas::init() { 00034 if (!m_initted) { 00035 if (NULL == m_renderer) { 00036 Scene *scene = new Scene(MaterialList(), new ShapeSet(false)); 00037 m_renderer = new OpenGLRenderer(new ThinLensCamera(), scene); 00038 } 00039 00040 Canvas::init(); 00041 } 00042 } 00043 00044 bool OpenGLCanvas::save(const char *fileName) { 00045 // technical Qt note: 00046 // renderPixmap creates a new, temporary GL context and renders this 00047 // OpenGLCanvas in that new context. this 'flushPreview' flag denotes to 00048 // Milton shapes / objects that prior display lists, textures, etc. have 00049 // been invalidated (because they don't cross over between GL contexts), 00050 // and therefore need to be recreated before using them; otherwise, 00051 // attempting to use a previously-compiled display list, for example, 00052 // would silently fail within renderPixmap. 00053 ResourceManager::insert<bool>("flushPreview", true); 00054 const QPixmap &temp = renderPixmap(); 00055 ResourceManager::insert<bool>("flushPreview", false); 00056 00057 return temp.save(QString(fileName), NULL, -1); 00058 } 00059 00060 00061 void OpenGLCanvas::lightOn(int light) { 00062 ASSERT(light >= 0 && light < 8); 00063 glEnable(GL_LIGHT0 + light); 00064 } 00065 00066 void OpenGLCanvas::lightOff(int light) { 00067 ASSERT(light >= 0 && light < 8); 00068 glDisable(GL_LIGHT0 + light); 00069 } 00070 00071 void OpenGLCanvas::lightPos(int light, float x, float y, float z) { 00072 ASSERT(light >= 0 && light < 8); 00073 GLfloat pos[4] = {x, y, z, 1}; 00074 00075 glPushMatrix(); 00076 glLoadIdentity(); 00077 glLightfv(GL_LIGHT0+light, GL_POSITION, pos); 00078 glPopMatrix(); 00079 } 00080 00081 void OpenGLCanvas::lightColor(int light, float r, float g, float b) { 00082 ASSERT(light >= 0 && light < 8); 00083 GLfloat color[4] = { r, g, b, 1}; 00084 00085 glLightfv(GL_LIGHT0+light, GL_DIFFUSE, color); 00086 glLightfv(GL_LIGHT0+light, GL_SPECULAR, color); 00087 } 00088 00089 void OpenGLCanvas::lightFunc(int light, float a, float b, float c) { 00090 ASSERT(light >= 0 && light < 8); 00091 00092 glLightf(GL_LIGHT0 + light, GL_CONSTANT_ATTENUATION, a); 00093 glLightf(GL_LIGHT0 + light, GL_LINEAR_ATTENUATION, b); 00094 glLightf(GL_LIGHT0 + light, GL_QUADRATIC_ATTENUATION, c); 00095 } 00096 00097 00098 bool OpenGLCanvas::supportsOpenGL() const { 00099 return true; 00100 } 00101 00102 00103 void OpenGLCanvas::mousePressEvent(QMouseEvent *e) { 00104 mousePressed(e); 00105 } 00106 00107 void OpenGLCanvas::mouseReleaseEvent(QMouseEvent *e) { 00108 mouseReleased(e); 00109 } 00110 00111 void OpenGLCanvas::mouseMoveEvent(QMouseEvent *e) { 00112 mouseMoved(e); 00113 } 00114 00115 void OpenGLCanvas::keyPressEvent(QKeyEvent *e) { 00116 keyPressed(e); 00117 } 00118 00119 void OpenGLCanvas::keyReleaseEvent(QKeyEvent *e) { 00120 keyReleased(e); 00121 } 00122 00123 00124 QSize OpenGLCanvas::sizeHint() const { 00125 return QSize(m_width, m_height); 00126 } 00127 00128 QSize OpenGLCanvas::minimumSize() const { 00129 return sizeHint(); 00130 } 00131 00132 QSize OpenGLCanvas::maximumSize() const { 00133 return sizeHint(); 00134 } 00135 00136 00137 void OpenGLCanvas::initializeGL() { 00138 qglClearColor(Qt::black); 00139 00140 glShadeModel(GL_SMOOTH); 00141 glDisable(GL_DITHER); 00142 glDisable(GL_NORMALIZE); 00143 glEnable(GL_DEPTH_TEST); 00144 00145 glEnable(GL_LIGHTING); 00146 for(int i = 8; i--;) { 00147 glDisable(GL_LIGHT0+i); 00148 lightFunc(i, 0, .5, .2); 00149 } 00150 00151 glColorMaterial(GL_FRONT, GL_DIFFUSE); 00152 glEnable(GL_MULTISAMPLE); 00153 glEnable(GL_CULL_FACE); 00154 00155 setDrawMode(m_drawMode); 00156 } 00157 00158 void OpenGLCanvas::redraw() { 00159 update(); 00160 } 00161 00162 void OpenGLCanvas::paintEvent(QPaintEvent *e) { 00163 int err; 00164 if ((err = glGetError()) != GL_NO_ERROR) { 00165 cerr << "GL is in an error state before call to paintGL()" << endl; 00166 cerr << "(Error: " << gluErrorString(err) << ")\n"; 00167 assert(0); 00168 } 00169 00170 glMatrixMode(GL_MODELVIEW); 00171 glPushMatrix(); 00172 00173 { // reset lighting 00174 glEnable(GL_LIGHTING); 00175 for(int i = 8; i--;) { 00176 glDisable(GL_LIGHT0 + i); 00177 lightFunc(i, .5, .2, 0); 00178 } 00179 00180 glColorMaterial(GL_FRONT, GL_DIFFUSE); 00181 glEnable(GL_COLOR_MATERIAL); 00182 00183 if (ResourceManager::getValue<bool>("enableDefaultLighting", true)) { 00184 const real_t p = 4.5; 00185 unsigned index = 0; 00186 00187 for(int dim = 3; dim--;) { 00188 real_t pos[3] = { 1, 1, 1 }; 00189 00190 for(real_t sign = -1; sign <= 1; sign += 2) { 00191 pos[dim] = sign * p; 00192 pos[(dim + 1) % 3] *= (dim + 1); 00193 pos[(dim + 2) % 3] *= (dim + 1); 00194 00195 lightOn(index); 00196 lightPos(index, pos[0], pos[1], pos[2]); 00197 lightFunc(index, .5, (2-sign)/4.0, 0); 00198 00199 const real_t power = 1; 00200 lightColor(index, power, power, power); 00201 00202 ++index; 00203 } 00204 } 00205 00206 lightOn(index); 00207 lightPos(index, 2, 2, 2); 00208 lightFunc(index, 1, .3, 0); 00209 lightColor(index, 1, 1, 1); 00210 ++index; 00211 00212 // attempt to place a light at the center of the scene's bounding box 00213 if (m_renderer) { 00214 Scene *scene = m_renderer->getScene(); 00215 00216 if (scene) { 00217 ShapeSet *shapes = scene->getShapes(); 00218 00219 if (shapes) { 00220 const Point3 &p = shapes->getAABB().getCenter(); 00221 00222 lightOn(index); 00223 lightPos(index, p[0], p[1], p[2]); 00224 lightFunc(index, .5, 0, 0); 00225 lightColor(index, 1, 1, 1); 00226 } 00227 } 00228 } 00229 } 00230 } 00231 00232 int oldDrawMode = m_drawMode; 00233 if (m_renderer && m_renderer->supportsOpenGL()) 00234 m_renderer->render(); 00235 00236 /* Notify all listeners of the paintGL event */ 00237 ListenerListIter iter; 00238 00239 for(iter = m_interactionListeners.begin(); iter != m_interactionListeners.end(); iter++) { 00240 (*iter)->paintGL(); 00241 } 00242 00243 glMatrixMode(GL_MODELVIEW); 00244 glPopMatrix(); 00245 00246 setDrawMode(oldDrawMode); 00247 00248 /* Notify all listeners of the paint event */ 00249 QPainter painter(this); 00250 painter.setRenderHint(QPainter::Antialiasing); 00251 00252 for(iter = m_interactionListeners.begin(); iter != m_interactionListeners.end(); iter++) { 00253 (*iter)->paint(&painter); 00254 } 00255 00256 if ((err = glGetError()) != GL_NO_ERROR) { 00257 cerr << "GL is in an error state after call to paintGL()" << endl; 00258 cerr << "(Error: " << gluErrorString(err) << ")\n"; 00259 assert(0); 00260 } 00261 } 00262 00263 void OpenGLCanvas::resizeGL(int width, int height) { 00264 glViewport(0, 0, width, height); 00265 } 00266 00267 void OpenGLCanvas::setDrawMode(int style) { 00268 makeCurrent(); 00269 00270 if (style == MODE_WIREFRAME) 00271 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 00272 else // MODE_SOLID 00273 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 00274 00275 m_drawMode = style; 00276 } 00277 00278 00279 void OpenGLCanvas::_init(bool defaultInteractionListeners) { 00280 _setupQWidget(); 00281 00282 if (defaultInteractionListeners) { 00283 registerInteractionListener(new CameraUIListener(this)); 00284 } 00285 } 00286 00287 void OpenGLCanvas::_setupQWidget() { 00288 // minor optimization: tell Qt that we'll be painting our own background 00289 setAutoFillBackground(false); 00290 setAttribute(Qt::WA_NoSystemBackground); 00291 setFocusPolicy(Qt::StrongFocus); 00292 00293 if (layout() != NULL) 00294 layout()->setSizeConstraint(QLayout::SetFixedSize); 00295 00296 setMouseTracking(true); 00297 setFixedSize(m_width, m_height); 00298 00299 // display a message if OpenGL is not supported 00300 // (over remote login, for example) 00301 if (!QGLFormat::hasOpenGL()) { 00302 dprintf("\nERROR: OpenGL not supported on this device!\n" 00303 "\t(OpenGLCanvas is invalid)\n\n"); 00304 } 00305 } 00306
Generated on 28 Feb 2009 for Milton by
1.5.6