fix for gl in windows
[mldemos:baraks-mldemos.git] / Core / glwidget.cpp
1 #include <QtGui>\r
2 #include <QtOpenGL>\r
3 #include <QtOpenGL/QGLFunctions>\r
4 #include <QtOpenGL/QGLShaderProgram>\r
5 #include <QDebug>\r
6 \r
7 #include <math.h>\r
8 #include <mymaths.h>\r
9 #include "glwidget.h"\r
10 #include <MathLib/MathLib.h>\r
11 #include "glUtils.h"\r
12 \r
13 #define ZoomZero 0.0125f\r
14 using namespace std;\r
15 \r
16 bool bDisplayShadows = false;\r
17 QMatrix4x4 lightMvMatrix;\r
18 QMatrix4x4 lightPMatrix;\r
19 QMatrix4x4 lightMvpMatrix;\r
20 QGLFramebufferObject *lightBlur_fbo;\r
21 QLabel *lightLabel = 0;\r
22 \r
23 void checkGL()\r
24 {\r
25     GLenum errors = glGetError();\r
26     switch(errors)\r
27     {\r
28     case GL_INVALID_ENUM:\r
29         qDebug() << "Function called with inappropriate enum.";\r
30         break;\r
31     case GL_INVALID_VALUE:\r
32         qDebug() << "Function called with out of range numeric value.";\r
33     case GL_INVALID_OPERATION:\r
34         qDebug() << "Operation performed out of context, or not allowed in the current state";\r
35         break;\r
36     case GL_INVALID_FRAMEBUFFER_OPERATION:\r
37         qDebug() << "Framebuffer object is not complete yet";\r
38         break;\r
39     case GL_OUT_OF_MEMORY:\r
40         qDebug() << "Out of Memory";\r
41         break;\r
42     }\r
43 }\r
44 \r
45 GLWidget::GLWidget(Canvas *canvas, QWidget *parent)\r
46     : QGLWidget(QGLFormat(QGL::SampleBuffers),parent), canvas(canvas), zoomFactor(ZoomZero), mutex(new QMutex())\r
47     //    : QGLWidget(QGLFormat(QGL::SampleBuffers|QGL::AlphaChannel),parent), canvas(canvas), zoomFactor(ZoomZero)\r
48 {\r
49     bDisplaySamples=bDisplayLines=bDisplaySurfaces=bDisplayTransparency=bDisplayBlurry=true;\r
50     bRotateCamera=false;\r
51     makeCurrent();\r
52 #ifdef WIN32\r
53     initializeGLFunctions(this->context());\r
54 #endif\r
55     width = 800;\r
56     height = 600;\r
57 \r
58     if (QGLFramebufferObject::hasOpenGLFramebufferBlit()) {\r
59         QGLFramebufferObjectFormat format;\r
60         format.setSamples(8);\r
61         format.setAttachment(QGLFramebufferObject::CombinedDepthStencil);\r
62 \r
63         render_fbo = new QGLFramebufferObject(width, height, format);\r
64         texture_fbo = new QGLFramebufferObject(width, height);\r
65     } else {\r
66         render_fbo = new QGLFramebufferObject(width*2, height*2);\r
67         texture_fbo = render_fbo;\r
68     }\r
69     QGLFramebufferObjectFormat format;\r
70     format.setAttachment(QGLFramebufferObject::CombinedDepthStencil);\r
71     light_fbo = new QGLFramebufferObject(width,height, format);\r
72     lightBlur_fbo = new QGLFramebufferObject(width,height);\r
73     xRot = yRot = zRot = 0;\r
74     xPos = yPos = zPos = 0.f;\r
75 \r
76     if(parent) resize(parent->width(), parent->height());\r
77     startTimer(20);\r
78 }\r
79 \r
80 void GLWidget::timerEvent(QTimerEvent *)\r
81 {\r
82     if(bRotateCamera) setYRotation(yRot + 3.f);\r
83     repaint();\r
84 }\r
85 \r
86 GLWidget::~GLWidget()\r
87 {\r
88     makeCurrent();\r
89     clearLists();\r
90     FOR(i, textureCount) delete [] textureData[i];\r
91     delete [] textureData;\r
92     textureData = 0;\r
93 }\r
94 \r
95 void GLWidget::AddObject(GLObject &o)\r
96 {\r
97     objects.push_back(o);\r
98     objectAlive.push_back(true);\r
99 }\r
100 \r
101 void GLWidget::SetObject(int index, GLObject &o)\r
102 {\r
103     if (index < 0 || index > objects.size()) return;\r
104     objects[index] = o;\r
105     objectAlive[index] = true;\r
106 }\r
107 \r
108 void GLWidget::clearLists()\r
109 {\r
110     mutex->lock();\r
111     FOR(i, drawSampleLists.size())\r
112     {\r
113         glDeleteLists(drawSampleLists[i], 1);\r
114     }\r
115     FOR(i, drawLists.size())\r
116     {\r
117         glDeleteLists(drawLists[i], 1);\r
118     }\r
119     drawSampleLists.clear();\r
120     drawLists.clear();\r
121     drawSampleListCenters.clear();\r
122     killList.resize(objects.size());\r
123     FOR(i, objects.size()) killList[i] = i;\r
124     mutex->unlock();\r
125 }\r
126 \r
127 void GLWidget::killObjects()\r
128 {\r
129     if(!killList.size()) return;\r
130     objectAlive.resize(objects.size(), true);\r
131     std::sort(killList.begin(), killList.end(), std::greater<int>());\r
132     FOR(i, killList.size())\r
133     {\r
134 #ifdef WIN32\r
135         qDebug() << "killing object " << killList[i] << "->" << objects[killList[i]].objectType;\r
136         //objects.erase(objects.begin() + killList[i]);\r
137         objectAlive[killList[i]] = false;\r
138         GLObject &o = objects[killList[i]];\r
139         o.vertices.clear();\r
140         //o.barycentric.clear();\r
141         //o.colors.clear();\r
142         //o.normals.clear();\r
143 #else\r
144         objects.erase(objects.begin() + killList[i]);\r
145         objectAlive.erase(objectAlive.begin() + killList[i]);\r
146 #endif\r
147     }\r
148     killList.clear();\r
149     FOR(i, objects.size())\r
150     {\r
151         qDebug() << i << (objectAlive[i] ? "alive" : "dead") << "->" << objects[i].objectType << "->" << objects[i].vertices.size();\r
152     }\r
153 }\r
154 \r
155 void GLWidget::initializeGL()\r
156 {\r
157     textureData = new unsigned char*[textureCount];\r
158     // first we generate the samples sprite (a circle with a black c)\r
159     FOR(i, textureCount)\r
160     {\r
161         textureData[i] = new unsigned char[texWidth*texHeight*4];\r
162         unsigned char *pData = textureData[i];\r
163         FOR(y, texHeight)\r
164         {\r
165             FOR(x, texWidth)\r
166             {\r
167                 int offs = (x + y*texWidth) * 4;\r
168                 float xoffs = ((float)x - texHalfWidth) / texHalfWidth;\r
169                 float yoffs = ((float)y - texHalfWidth) / texHalfHeight;\r
170                 float r = std::sqrt(xoffs*xoffs + yoffs*yoffs);\r
171                 switch (i)\r
172                 {\r
173                 case 0: // samples\r
174                 {\r
175                     if(r < 0.7)\r
176                     {\r
177                         pData[offs + 0] = 255; //r\r
178                         pData[offs + 1] = 255; //g\r
179                         pData[offs + 2] = 255; //b\r
180                         pData[offs + 3] = 255; // *\r
181                     }\r
182                     else if (r < 0.95)\r
183                     {\r
184                         pData[offs + 0] = 0; //r\r
185                         pData[offs + 1] = 0; //g\r
186                         pData[offs + 2] = 0; //b\r
187                         pData[offs + 3] = 255; // *\r
188                     }\r
189                     else\r
190                     {\r
191                         pData[offs + 0] = 255; //r\r
192                         pData[offs + 1] = 255; //g\r
193                         pData[offs + 2] = 255; //b\r
194                         pData[offs + 3] = 0; // *\r
195                     }\r
196                 }\r
197                     break;\r
198                 case 1: // wide circle\r
199                 {\r
200                     if(r > 0.6 && r < 0.8)\r
201                     {\r
202                         pData[offs + 0] = 255; //r\r
203                         pData[offs + 1] = 255; //g\r
204                         pData[offs + 2] = 255; //b\r
205                         pData[offs + 3] = 255; // *\r
206                     }\r
207                     else if(r > 0.5 && r < 0.95) // the outlines\r
208                     {\r
209                         pData[offs + 0] = 0; //r\r
210                         pData[offs + 1] = 0; //g\r
211                         pData[offs + 2] = 0; //b\r
212                         pData[offs + 3] = 255; // *\r
213                     }\r
214                     else\r
215                     {\r
216                         pData[offs + 0] = 255; //r\r
217                         pData[offs + 1] = 255; //g\r
218                         pData[offs + 2] = 255; //b\r
219                         pData[offs + 3] = 0; // *\r
220                     }\r
221                 }\r
222                     break;\r
223                 case 2: // fuzzy particle\r
224                 {\r
225                     pData[offs + 0] = 255*(1.f-r);\r
226                     pData[offs + 1] = 255*(1.f-r);\r
227                     pData[offs + 2] = 255*(1.f-r);\r
228                     pData[offs + 3] = 255;\r
229                 }\r
230                     break;\r
231                 }\r
232             }\r
233         }\r
234     }\r
235 \r
236     glGenTextures(2, textureNames); // 0: samples, 1: wide circles\r
237     glEnable(GL_TEXTURE_2D);\r
238     glActiveTexture(GL_TEXTURE0);\r
239 \r
240     FOR(i, textureCount)\r
241     {\r
242         glBindTexture(GL_TEXTURE_2D, textureNames[i]);\r
243         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData[i]);\r
244     }\r
245     glEnable(GL_POINT_SPRITE);\r
246     glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);\r
247     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);\r
248     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);\r
249     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);\r
250     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);\r
251     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);\r
252 \r
253     glEnable(GL_BLEND);\r
254     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\r
255     glEnable(GL_DEPTH_TEST);\r
256     glDepthFunc(GL_LEQUAL);\r
257 \r
258     glEnable( GL_POINT_SMOOTH );\r
259 \r
260     // Somewhere in the initialization part of your programâ\80¦\r
261     glEnable(GL_LIGHTING);\r
262     glEnable(GL_LIGHT0);\r
263 \r
264     // Create light components\r
265     GLfloat ambientLight[] = { 0.2f, 0.2f, 0.2f, 1.0f };\r
266     GLfloat diffuseLight[] = { 0.8f, 0.8f, 0.8, 1.0f };\r
267     GLfloat specularLight[] = { 0.5f, 0.5f, 0.5f, 1.0f };\r
268     //GLfloat position[] = { -1.5f, 1.0f, -4.0f, 1.0f };\r
269     GLfloat position[] = { 10.0f, 10.0f, 10.0f, 1.0f };\r
270 \r
271     // Assign created components to GL_LIGHT0\r
272     glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);\r
273     glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);\r
274     glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight);\r
275     glLightfv(GL_LIGHT0, GL_POSITION, position);\r
276     glEnable(GL_NORMALIZE); // so that when we scale stuff, the lighting doesnt go bonkers\r
277 \r
278     // We initialize the lights\r
279     GLLight light;\r
280     light.SetAmbient(0.1,0.1,0.1);\r
281     light.SetDiffuse(0.8,0.8,0.8);\r
282     light.SetSpecular(1.0,1.0,1.0);\r
283     light.SetPosition(50.0f, 0.0f, 0.0f);\r
284     lights.push_back(light);\r
285     light.SetAmbient(0,0,0);\r
286     light.SetSpecular(0,0,0);\r
287     light.SetPosition(-50.0f, 50.0f, -50.0f);\r
288     lights.push_back(light);\r
289     light.SetPosition(50.0f, 50.0f, 50.0f);\r
290     lights.push_back(light);\r
291 \r
292     // We initialize the shaders\r
293     QGLShaderProgram *program=0;\r
294     LoadShader(&program,":/MLDemos/shaders/drawSamples.vsh",":/MLDemos/shaders/drawSamples.fsh");\r
295     program->bindAttributeLocation("vertex", 0);\r
296     program->bindAttributeLocation("color", 1);\r
297     shaders["Samples"] = program;\r
298     program = 0;\r
299     LoadShader(&program,":/MLDemos/shaders/smoothTransparent.vsh",":/MLDemos/shaders/smoothTransparent.fsh");\r
300     program->bindAttributeLocation("vertex", 0);\r
301     program->bindAttributeLocation("vertexNormal", 1);\r
302     program->bindAttributeLocation("vertexColor", 2);\r
303     program->bindAttributeLocation("barycentric", 3);\r
304     shaders["SmoothTransparent"] = program;\r
305     program = 0;\r
306     LoadShader(&program, ":/MLDemos/shaders/renderFBO.vsh", ":/MLDemos/shaders/renderFBO.fsh");\r
307     program->bindAttributeLocation("vertex",0);\r
308     shaders["RenderFBO"] = program;\r
309     program = 0;\r
310     LoadShader(&program, ":/MLDemos/shaders/blurFBO.vsh", ":/MLDemos/shaders/blurFBO.fsh");\r
311     program->bindAttributeLocation("vertex",0);\r
312     shaders["BlurFBO"] = program;\r
313     program = 0;\r
314     LoadShader(&program,":/MLDemos/shaders/depthSamples.vsh",":/MLDemos/shaders/depthSamples.fsh");\r
315     program->bindAttributeLocation("vertex", 0);\r
316     shaders["DepthSamples"] = program;\r
317     program = 0;\r
318     LoadShader(&program,":/MLDemos/shaders/drawSamplesShadow.vsh",":/MLDemos/shaders/drawSamplesShadow.fsh");\r
319     program->bindAttributeLocation("vertex", 0);\r
320     program->bindAttributeLocation("color", 1);\r
321     shaders["SamplesShadow"] = program;\r
322 \r
323     glEnable(GL_MULTISAMPLE);\r
324     //glClearColor(0.5f, 0.5f, 0.5f, 1.0f);\r
325     glClearColor(1.f, 1.f, 1.f, 1.0f);\r
326 \r
327 }\r
328 \r
329 void GLWidget::generateObjects()\r
330 {\r
331     if(!canvas) return;\r
332     int xIndex = canvas->xIndex;\r
333     int yIndex = canvas->yIndex;\r
334     int zIndex = canvas->zIndex;\r
335     int dim = canvas->data->GetDimCount();\r
336 \r
337     // we generate the canvas samples\r
338     GLObject oSamples;\r
339     oSamples.objectType = "Samples,Canvas";\r
340     FOR(i, canvas->data->GetCount())\r
341     {\r
342         fvec sample = canvas->data->GetSample(i);\r
343         if(canvas->data->GetFlag(i) == _TRAJ) continue; // we don't want to draw trajectories\r
344         oSamples.vertices.append(QVector3D(xIndex >= 0 && xIndex < dim ? sample[xIndex] : 0,\r
345                                            yIndex >= 0 && yIndex < dim ? sample[yIndex] : 0,\r
346                                            zIndex >= 0 && zIndex < dim ? sample[zIndex] : 0));\r
347         QColor color = SampleColor[canvas->data->GetLabel(i)%SampleColorCnt];\r
348         oSamples.colors.append(QVector4D(color.redF(), color.greenF(), color.blueF(),1));\r
349     }\r
350     // aaand the trajectories\r
351     ivec trajLabels(canvas->data->GetSequences().size());\r
352     FOR(i, canvas->data->GetSequences().size()) trajLabels[i] = canvas->data->GetLabel(canvas->data->GetSequences()[i].first);\r
353     vector< vector<fvec> > trajectories = canvas->data->GetTrajectories(canvas->trajectoryResampleType,\r
354                                                                         canvas->trajectoryResampleCount,\r
355                                                                         canvas->trajectoryCenterType, 0.1, true);\r
356     vector<GLObject> oTrajs;\r
357     FOR(i, trajectories.size())\r
358     {\r
359         GLObject o;\r
360         FOR(j, trajectories[i].size())\r
361         {\r
362             fvec sample = trajectories[i][j];\r
363             o.vertices.append(QVector3D(xIndex >= 0 && xIndex < dim ? sample[xIndex] : 0,\r
364                                         yIndex >= 0 && yIndex < dim ? sample[yIndex] : 0,\r
365                                         zIndex >= 0 && zIndex < dim ? sample[zIndex] : 0));\r
366             QColor color = SampleColor[trajLabels[i]%SampleColorCnt];\r
367             o.colors.append(QVector4D(color.redF(), color.greenF(), color.blueF(),1));\r
368         }\r
369         o.objectType = "Samples,Canvas,trajectories";\r
370         o.style ="pointsize:5,width:0.5,dotted";\r
371         oTrajs.push_back(o);\r
372     }\r
373 \r
374     // and we replace the current objects with them\r
375     bool bReplacedSamples=false;\r
376     FOR(i, objects.size())\r
377     {\r
378         if(objects[i].objectType.contains("trajectories"))\r
379         {\r
380             objects.erase(objects.begin()+i);\r
381             objectAlive.erase(objectAlive.begin() + i);\r
382             i--;\r
383         }\r
384         else if(!bReplacedSamples && objects[i].objectType.contains("Samples,Canvas"))\r
385         {\r
386             objects[i] = oSamples;\r
387             objectAlive[i] = true;\r
388             bReplacedSamples = true;\r
389         }\r
390     }\r
391     if(!bReplacedSamples)\r
392     {\r
393         objects.push_back(oSamples);\r
394         objectAlive.push_back(true);\r
395     }\r
396     objects.insert(objects.end(),oTrajs.begin(),oTrajs.end());\r
397     objectAlive.resize(objects.size(), true);\r
398 \r
399     if(!canvas->maps.reward.isNull())\r
400     {\r
401         int rewardIndex = -1;\r
402         FOR(i, objects.size())\r
403         {\r
404             if(objects[i].objectType.contains("Reward"))\r
405             {\r
406                 rewardIndex = i;\r
407                 break;\r
408             }\r
409         }\r
410         if(rewardIndex == -1)\r
411         {\r
412             int w = canvas->maps.reward.width();\r
413             int h = canvas->maps.reward.height();\r
414             float ratio = h/(float)w;\r
415             int xSteps = 100;\r
416             int ySteps = h * xSteps / w;\r
417             //int ySteps = h * xSteps / w;\r
418             QImage rewardImage = canvas->maps.reward.scaled(xSteps,ySteps,Qt::KeepAspectRatioByExpanding).toImage();\r
419             QRgb *pixels = (QRgb*) rewardImage.bits();\r
420             float *values = new float[xSteps*ySteps];\r
421             float maxData = 0;\r
422             FOR(i, xSteps*ySteps)\r
423             {\r
424                 values[i] = 1.f - qBlue(pixels[i])/255.f; // all data is in a 0-1 range\r
425                 maxData = max(maxData, values[i]);\r
426             }\r
427             if(maxData > 0)\r
428             {\r
429                 FOR(i, xSteps*ySteps) values[i] = values[i]/maxData*0.5f; // we ensure that the data is normalized\r
430             }\r
431             fvec mins(3,-1.f);\r
432             fvec maxes(3,1.f);\r
433             fflush(stdout);\r
434             GLObject o = GenerateMeshGrid(values, xSteps, ySteps, mins, maxes, 0, 2, 1);\r
435             o.objectType = "Surfaces,Reward,quads";\r
436             o.style = "smooth,color:1:0.7:0.7:1,specularity:0.2,shininess:8";\r
437             objects.push_back(o);\r
438             objectAlive.push_back(true);\r
439             KILL(values);\r
440             printf("reward mesh generated: %d vertices (%d normals)\n", o.vertices.size(), o.normals.size());fflush(stdout);\r
441         }\r
442     }\r
443 }\r
444 \r
445 void GLWidget::DrawObject(GLObject &o)\r
446 {\r
447     if(!o.vertices.size()) return;\r
448     if(bDisplaySamples && o.objectType.contains("Samples")) DrawSamples(o);\r
449     if(bDisplayLines && o.objectType.contains("Lines") || o.objectType.contains("trajectories")) DrawLines(o);\r
450     else if(bDisplaySurfaces && o.objectType.contains("Surfaces")) DrawSurfaces(o);\r
451     else if(bDisplayLines && o.objectType.contains("Particles")) DrawParticles(o);\r
452 }\r
453 \r
454 void GLWidget::DrawParticles(GLObject &o)\r
455 {\r
456     QString style = o.style.toLower();\r
457     float pointSize = 12.f;\r
458     if(style.contains("pointsize"))\r
459     {\r
460         QStringList params = style.split(",");\r
461         FOR(i, params.size())\r
462         {\r
463             if(params[i].contains("pointsize"))\r
464             {\r
465                 QStringList p = params[i].split(":");\r
466                 pointSize = p.at(1).toFloat();\r
467                 break;\r
468             }\r
469         }\r
470     }\r
471 \r
472     QGLShaderProgram *program = shaders["Samples"];\r
473     program->bind();\r
474     program->enableAttributeArray(0);\r
475     program->enableAttributeArray(1);\r
476     program->setAttributeArray(0, o.vertices.constData());\r
477     program->setAttributeArray(1, o.colors.constData());\r
478     program->setUniformValue("matrix", modelViewProjectionMatrix);\r
479 \r
480     glPushAttrib(GL_ALL_ATTRIB_BITS);\r
481     glDisable(GL_LIGHTING);\r
482     glEnable(GL_DEPTH_TEST);\r
483     glDepthMask(GL_TRUE);\r
484     glEnable(GL_BLEND);\r
485     glEnable(GL_ALPHA_TEST);\r
486     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\r
487 \r
488     glEnable(GL_TEXTURE_2D);\r
489     glBindTexture(GL_TEXTURE_2D, GLWidget::textureNames[2]);\r
490     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);\r
491     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);\r
492     program->setUniformValue("color_texture", 0);\r
493     glEnable(GL_PROGRAM_POINT_SIZE_EXT);\r
494     glPointSize(pointSize);\r
495 \r
496     // we actually draw stuff!\r
497     glDrawArrays(GL_POINTS,0,o.vertices.size());\r
498     glPopAttrib();\r
499 \r
500     program->release();\r
501 }\r
502 \r
503 void GLWidget::DrawSamples(GLObject &o)\r
504 {\r
505     QString style = o.style.toLower();\r
506     float pointSize = 12.f;\r
507     if(style.contains("pointsize"))\r
508     {\r
509         QStringList params = style.split(",");\r
510         FOR(i, params.size())\r
511         {\r
512             if(params[i].contains("pointsize"))\r
513             {\r
514                 QStringList p = params[i].split(":");\r
515                 pointSize = p.at(1).toFloat();\r
516                 break;\r
517             }\r
518         }\r
519     }\r
520 \r
521     QGLShaderProgram *program = bDisplayShadows ? shaders["SamplesShadow"] : shaders["Samples"];\r
522     program->bind();\r
523     checkGL();\r
524     program->enableAttributeArray(0);\r
525     checkGL();\r
526     program->enableAttributeArray(1);\r
527     checkGL();\r
528     program->setAttributeArray(0, o.vertices.constData());\r
529     checkGL();\r
530     program->setAttributeArray(1, o.colors.constData());\r
531     checkGL();\r
532     program->setUniformValue("matrix", modelViewProjectionMatrix);\r
533     checkGL();\r
534 \r
535     glPushAttrib(GL_ALL_ATTRIB_BITS);\r
536     checkGL();\r
537     glDisable(GL_LIGHTING);\r
538     checkGL();\r
539     glEnable(GL_DEPTH_TEST);\r
540     checkGL();\r
541     glDepthMask(GL_TRUE);\r
542     checkGL();\r
543     glEnable(GL_BLEND);\r
544     checkGL();\r
545     glEnable(GL_ALPHA_TEST);\r
546     checkGL();\r
547     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\r
548     checkGL();\r
549 \r
550     glActiveTexture(GL_TEXTURE0);\r
551     checkGL();\r
552     glEnable(GL_TEXTURE_2D);\r
553     checkGL();\r
554     glEnable(GL_POINT_SPRITE);\r
555     checkGL();\r
556     if(o.style.contains("rings")) glBindTexture(GL_TEXTURE_2D, GLWidget::textureNames[1]);\r
557     else glBindTexture(GL_TEXTURE_2D, GLWidget::textureNames[0]);\r
558     checkGL();\r
559     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);\r
560     checkGL();\r
561     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);\r
562     checkGL();\r
563     program->setUniformValue("color_texture", 0);\r
564     checkGL();\r
565 \r
566     if(bDisplayShadows)\r
567     {\r
568         glEnable(GL_LIGHTING);\r
569         checkGL();\r
570         program->setUniformValue("lightMvpMatrix", lightMvpMatrix);\r
571         program->setUniformValue("lightMvMatrix", lightMvMatrix);\r
572         glActiveTexture(GL_TEXTURE1);\r
573         checkGL();\r
574         glEnable(GL_TEXTURE_2D);\r
575         checkGL();\r
576         glBindTexture(GL_TEXTURE_2D, light_fbo->texture());\r
577         checkGL();\r
578         program->setUniformValue("shadow_texture", 1);\r
579         program->setUniformValue("pointSize", pointSize);\r
580         glActiveTexture(GL_TEXTURE0);\r
581         checkGL();\r
582     }\r
583 \r
584     glEnable(GL_PROGRAM_POINT_SIZE_EXT);\r
585     checkGL();\r
586     glPointSize(pointSize);\r
587     checkGL();\r
588 \r
589     // we actually draw stuff!\r
590     glDrawArrays(GL_POINTS,0,o.vertices.size());\r
591     checkGL();\r
592 \r
593     glPopAttrib();\r
594     checkGL();\r
595 \r
596     program->release();\r
597 }\r
598 \r
599 void GLWidget::DrawLines(GLObject &o)\r
600 {\r
601     glPushAttrib(GL_ALL_ATTRIB_BITS);\r
602     glDisable(GL_LIGHTING);\r
603     glDisable(GL_TEXTURE_2D);\r
604     glDisable(GL_POINT_SPRITE);\r
605 \r
606     glEnable(GL_LINE_SMOOTH);\r
607     glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);\r
608     glEnable(GL_BLEND);\r
609     glEnable(GL_ALPHA_TEST);\r
610     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\r
611 \r
612     QString style = o.style.toLower();\r
613     if(style.contains("dotted")) glEnable(GL_LINE_STIPPLE);\r
614     else glDisable(GL_LINE_STIPPLE);\r
615 \r
616     glLineWidth(1.f);\r
617     glLineStipple (3, 0xFFFF);\r
618     glColor3f(0,0,0);\r
619 \r
620     int fading = 0;\r
621     QStringList params = style.split(",");\r
622     FOR(i, params.size())\r
623     {\r
624         if(params[i].contains("fading"))\r
625         {\r
626             QStringList p = params[i].split(":");\r
627             fading = p[1].toInt();\r
628         }\r
629         if(params[i].contains("width"))\r
630         {\r
631             QStringList p = params[i].split(":");\r
632             float val = p[1].toFloat();\r
633             glLineWidth(val);\r
634         }\r
635         if(params[i].contains("linecolor"))\r
636         {\r
637             QStringList p = params[i].split(":");\r
638             float r = p[1].toFloat();\r
639             float g = p[2].toFloat();\r
640             float b = p[3].toFloat();\r
641             glColor3f(r,g,b);\r
642         }\r
643         if(params[i].contains("pattern"))\r
644         {\r
645             QStringList p = params[i].split(":");\r
646             int factor = p[1].toInt();\r
647             int pattern = p[2].toInt();\r
648             glLineStipple (factor, pattern);\r
649         }\r
650     }\r
651 \r
652     glPushMatrix();\r
653     glMultMatrixd(o.model.constData());\r
654     if(o.objectType.contains("linestrip") || o.objectType.contains("trajectories")) glBegin(GL_LINE_STRIP);\r
655     else glBegin(GL_LINES);\r
656     FOR(i, o.vertices.size())\r
657     {\r
658         glVertex3f(o.vertices.at(i).x(),o.vertices.at(i).y(),o.vertices.at(i).z());\r
659         float alpha = 1.f;\r
660         if(fading) alpha = 1.f - ((i/2)%fading)/float(fading);\r
661         if(!o.objectType.contains("trajectories") && i < o.colors.size()) glColor4f(o.colors[i].x(), o.colors[i].y(), o.colors[i].z(), alpha);\r
662         else glColor4f(0,0,0,alpha);\r
663     }\r
664     glEnd();\r
665     glPopMatrix();\r
666     glPopAttrib();\r
667 }\r
668 \r
669 void RecomputeBarycentric(GLObject &o)\r
670 {\r
671     o.barycentric.resize(o.vertices.size());\r
672     if(o.objectType.contains("quadstrip")){}\r
673     else if(o.objectType.contains("quads"))\r
674     {\r
675         FOR(i, o.vertices.size()/4)\r
676         {\r
677             int index = i*4;\r
678             o.barycentric[index  ] = QVector4D(1,1,1,1);\r
679             o.barycentric[index+1] = QVector4D(0,1,1,1);\r
680             o.barycentric[index+2] = QVector4D(0,0,1,1);\r
681             o.barycentric[index+3] = QVector4D(1,0,1,1);\r
682         }\r
683     }\r
684     else\r
685     {\r
686         FOR(i, o.vertices.size()/3)\r
687         {\r
688             int index = i*3;\r
689             o.barycentric[index  ] = QVector4D(1,0,0,1);\r
690             o.barycentric[index+1] = QVector4D(0,1,0,1);\r
691             o.barycentric[index+2] = QVector4D(0,0,1,1);\r
692         }\r
693     }\r
694 }\r
695 \r
696 void RecomputeNormals(GLObject &o)\r
697 {\r
698     // we need to go through all the faces\r
699     o.normals.resize(o.vertices.size());\r
700     if(o.objectType.contains("quadstrip")) {}\r
701     else if(o.objectType.contains("quads"))\r
702     {\r
703         QVector3D a,b;\r
704         QVector<QVector3D> faceNormals(o.vertices.size()/4);\r
705         FOR(i, o.vertices.size()/4) // for each quad\r
706         {\r
707             int index = i*4;\r
708             bool bInvert = false;\r
709             if(o.vertices[index] != o.vertices[index+1])\r
710             {\r
711                 a = o.vertices[index+1] - o.vertices[index];\r
712                 if(o.vertices[index] != o.vertices[index+3])\r
713                     b = o.vertices[index+3] - o.vertices[index];\r
714                 else\r
715                 {\r
716                     b = o.vertices[index+2] - o.vertices[index];\r
717                     bInvert = true;\r
718                 }\r
719             }\r
720             else\r
721             {\r
722                 a = o.vertices[index+2] - o.vertices[index];\r
723                 b = o.vertices[index+3] - o.vertices[index];\r
724                 bInvert = true;\r
725             }\r
726             faceNormals[i] = bInvert ? QVector3D::crossProduct(a,b) : QVector3D::crossProduct(b,a);\r
727             faceNormals[i].normalize();\r
728         }\r
729         if(o.vertices.size() < 65536) // if we have too many points it would be a tad too slow\r
730         {\r
731             // now that whe have these we need to know which vertices overlap\r
732             vector<int> twins(o.vertices.size());\r
733             FOR(i, twins.size()) twins[i] = i;\r
734             FOR(i, twins.size())\r
735             {\r
736                 if(twins[i] != i) // we have already computed its twin\r
737                 {\r
738                     o.normals[i] = o.normals[twins[i]];\r
739                     continue;\r
740                 }\r
741                 o.normals[i] = faceNormals[i/4];\r
742                 for(int j=i+1;j<twins.size();j++)\r
743                 {\r
744                     if(o.vertices[i] == o.vertices[j])\r
745                     {\r
746                         twins[j] = i;\r
747                         o.normals[i] += faceNormals[j/4];\r
748                     }\r
749                 }\r
750                 o.normals[i].normalize();\r
751             }\r
752         }\r
753         else // flatshaded crappy version\r
754         {\r
755             FOR(i, o.vertices.size())\r
756             {\r
757                 int faceIndex = i/4;\r
758                 o.normals[i] = faceNormals[faceIndex];\r
759             }\r
760         }\r
761     }\r
762     else\r
763     {\r
764         QVector<QVector3D> faceNormals(o.vertices.size()/3);\r
765         FOR(i, o.vertices.size()/3) // for each triangle\r
766         {\r
767             int index = i*3;\r
768             QVector3D a = o.vertices[index+1] - o.vertices[index];\r
769             QVector3D b = o.vertices[index+2] - o.vertices[index];\r
770             faceNormals[i] = QVector3D::crossProduct(b,a);\r
771             faceNormals[i].normalize();\r
772         }\r
773         if(o.vertices.size() < 65536) // if we have too many points it would be a tad too slow\r
774         {\r
775             // now that whe have these we need to know which vertices overlap\r
776             vector<int> twins(o.vertices.size());\r
777             FOR(i, twins.size()) twins[i] = i;\r
778             FOR(i, twins.size())\r
779             {\r
780                 o.normals[i] = faceNormals[i/3];\r
781                 if(twins[i] != i) // we have already passed by here\r
782                 {\r
783                     o.normals[i] = o.normals[twins[i]];\r
784                     continue;\r
785                 }\r
786                 for(int j=i+1;j<twins.size();j++)\r
787                 {\r
788                     if(o.vertices[i] == o.vertices[j])\r
789                     {\r
790                         twins[j] = i;\r
791                         o.normals[i] += faceNormals[j/3];\r
792                     }\r
793                 }\r
794                 o.normals[i].normalize();\r
795             }\r
796         }\r
797         else // flatshaded crappy version\r
798         {\r
799             FOR(i, o.vertices.size())\r
800             {\r
801                 int faceIndex = i/4;\r
802                 o.normals[i] = faceNormals[faceIndex];\r
803             }\r
804         }\r
805     }\r
806 }\r
807 \r
808 void GLWidget::DrawSurfaces(GLObject &o)\r
809 {\r
810     QString style = o.style.toLower();\r
811     QStringList params = style.split(",");\r
812     if(o.normals.size() != o.vertices.size()) // we need to recompute the normals\r
813     {\r
814         qDebug() << "recomputing normals";\r
815         RecomputeNormals(o);\r
816         qDebug() << "Done.";\r
817     }\r
818     if(o.colors.size() != o.vertices.size())\r
819     {\r
820         qDebug() << "filling in colors";\r
821         o.colors.resize(o.vertices.size());\r
822         FOR(i, o.vertices.size())\r
823         {\r
824             o.colors[i] = QVector4D(1,1,1,1);\r
825         }\r
826     }\r
827 \r
828     if(o.barycentric.size() != o.vertices.size())\r
829     {\r
830         qDebug() << "recomputing barycentrics";\r
831         RecomputeBarycentric(o);\r
832         qDebug() << "Done.";\r
833     }\r
834 \r
835     float specularity = 0.7f;\r
836     float shininess = 8.f;\r
837     float alpha = style.contains("transparent") ? 0.5f : 1.f;\r
838     QVector4D material(1,1,1,alpha);\r
839     float offset = 0.f;\r
840     FOR(i, params.size())\r
841     {\r
842         if(params[i].contains("color"))\r
843         {\r
844             QStringList p = params[i].split(":");\r
845             float r = p[1].toFloat();\r
846             float g = p[2].toFloat();\r
847             float b = p[3].toFloat();\r
848             if(p.size() > 4) alpha = p[4].toFloat();\r
849             material = QVector4D(r,g,b,alpha);\r
850         }\r
851         else if(params[i].contains("specularity"))\r
852         {\r
853             QStringList p = params[i].split(":");\r
854             specularity = p[1].toFloat();\r
855         }\r
856         else if(params[i].contains("shininess"))\r
857         {\r
858             QStringList p = params[i].split(":");\r
859             shininess = p[1].toFloat();\r
860         }\r
861         else if(params[i].contains("offset"))\r
862         {\r
863             QStringList p = params[i].split(":");\r
864             offset = p[1].toFloat();\r
865         }\r
866     }\r
867 \r
868     glPushAttrib(GL_ALL_ATTRIB_BITS);\r
869     glEnable(GL_LIGHTING);\r
870     glDisable(GL_TEXTURE_2D);\r
871     if(style.contains("smooth")) glShadeModel(GL_SMOOTH);\r
872     else glShadeModel (GL_FLAT);\r
873 \r
874     if(offset)\r
875     {\r
876         glPolygonOffset(offset, 1.0);\r
877         glEnable(GL_POLYGON_OFFSET_FILL);\r
878     }\r
879     //    glCullFace(GL_BACK);\r
880     //    glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);\r
881 \r
882     glEnable(GL_BLEND);\r
883     //glBlendEquation(GL_FUNC_ADD);\r
884     glEnable(GL_ALPHA_TEST);\r
885     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\r
886 \r
887     glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE | GL_SPECULAR);\r
888 \r
889     qDebug() << "enabling lights" << lights.size();\r
890     // setup lights\r
891     FOR(i, lights.size())\r
892     {\r
893         glEnable(GL_LIGHT0+i);\r
894         glLightfv(GL_LIGHT0+i, GL_AMBIENT, lights[i].ambientLight);\r
895         glLightfv(GL_LIGHT0+i, GL_DIFFUSE, lights[i].diffuseLight);\r
896         glLightfv(GL_LIGHT0+i, GL_SPECULAR, lights[i].specularLight);\r
897         glLightfv(GL_LIGHT0+i, GL_POSITION, lights[i].position);\r
898     }\r
899 \r
900     if(style.contains("smooth"))\r
901     {\r
902         QVector4D surfaceStyle(1,0,0,0);\r
903         if(style.contains("wireframe")) surfaceStyle.setY(1);\r
904         if(style.contains("isolines"))\r
905         {\r
906             surfaceStyle.setY(2 + 1); // by default we draw isolines on the vertical axis\r
907             QStringList params = style.split(",");\r
908             FOR(i, params.size())\r
909             {\r
910                 if(params[i].contains("isolines:"))\r
911                 {\r
912                     QStringList p = params[i].split(":");\r
913                     surfaceStyle.setY(2 + p[1].toFloat());\r
914                 }\r
915             }\r
916         }\r
917         if(style.contains("blurry")) surfaceStyle.setZ(1);\r
918         QMatrix4x4 mvMatrix = modelViewMatrix * o.model;\r
919         QMatrix4x4 mvpMatrix = perspectiveMatrix * mvMatrix;\r
920         QMatrix3x3 normMatrix = mvMatrix.normalMatrix();\r
921         QVector4D l0pos = modelViewMatrix * QVector4D(lights[0].position[0],\r
922                 lights[0].position[1],\r
923                 lights[0].position[2],\r
924                 lights[0].position[3]);\r
925         QVector4D l1pos = modelViewMatrix * QVector4D(lights[1].position[0],\r
926                 lights[1].position[1],\r
927                 lights[1].position[2],\r
928                 lights[1].position[3]);\r
929         QVector4D l2pos = modelViewMatrix * QVector4D(lights[2].position[0],\r
930                 lights[2].position[1],\r
931                 lights[2].position[2],\r
932                 lights[2].position[3]);\r
933         QGLShaderProgram *program = shaders["SmoothTransparent"];\r
934         program->bind();\r
935         program->setUniformValue("mvMatrix", mvMatrix);\r
936         program->setUniformValue("mvpMatrix", mvpMatrix);\r
937         program->setUniformValue("normalMatrix", normMatrix);\r
938         program->setUniformValue("viewport", viewport);\r
939         program->setUniformValue("materialColor", material);\r
940         program->setUniformValue("surfaceStyle", surfaceStyle);\r
941         program->setUniformValue("specularity", specularity);\r
942         program->setUniformValue("shininess", shininess);\r
943         program->setUniformValue("transparency", bDisplayTransparency);\r
944         program->setUniformValueArray("lights[0].position", &l0pos,1);\r
945         program->setUniformValueArray("lights[0].ambient", lights[0].ambientLight,1,4);\r
946         program->setUniformValueArray("lights[0].diffuse", lights[0].diffuseLight,1,4);\r
947         program->setUniformValueArray("lights[0].specular", lights[0].specularLight,1,4);\r
948         program->setUniformValueArray("lights[1].position", &l1pos,1);\r
949         program->setUniformValueArray("lights[1].ambient", lights[1].ambientLight,1,4);\r
950         program->setUniformValueArray("lights[1].diffuse", lights[1].diffuseLight,1,4);\r
951         program->setUniformValueArray("lights[1].specular", lights[1].specularLight,1,4);\r
952         program->setUniformValueArray("lights[2].position", &l2pos,1);\r
953         program->setUniformValueArray("lights[2].ambient", lights[2].ambientLight,1,4);\r
954         program->setUniformValueArray("lights[2].diffuse", lights[2].diffuseLight,1,4);\r
955         program->setUniformValueArray("lights[2].specular", lights[2].specularLight,1,4);\r
956         program->enableAttributeArray(0);\r
957         program->enableAttributeArray(1);\r
958         program->enableAttributeArray(2);\r
959         program->enableAttributeArray(3);\r
960         program->setAttributeArray(0, o.vertices.constData());\r
961         program->setAttributeArray(1, o.normals.constData());\r
962         program->setAttributeArray(2, o.colors.constData());\r
963         program->setAttributeArray(3, o.barycentric.constData());\r
964 \r
965         GLenum mode = GL_TRIANGLES;\r
966         if(o.objectType.contains("quadstrip")) mode = GL_QUAD_STRIP;\r
967         else if(o.objectType.contains("quads")) mode = GL_QUADS;\r
968         glDrawArrays(mode, 0, o.vertices.size());\r
969         program->release();\r
970     }\r
971     else\r
972     {\r
973         GLfloat whiteSpecularMaterial[] = {1.0, 1.0, 1.0};\r
974         GLfloat shininess[] = {128}; //set the shininess of the\r
975         glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, whiteSpecularMaterial);\r
976         glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, shininess);\r
977 \r
978         glColor4f(material.x(), material.y(), material.z(), material.w());\r
979         float model[16];\r
980         FOR(i, 16) model[i] = o.model.constData()[i];\r
981         glPushMatrix();\r
982         glMultMatrixf(model);\r
983         if(o.objectType.contains("quadstrip")) glBegin(GL_QUAD_STRIP);\r
984         else if(o.objectType.contains("quads")) glBegin(GL_QUADS);\r
985         else glBegin(GL_TRIANGLES);\r
986         FOR(i, o.vertices.size())\r
987         {\r
988             glNormal3f(o.normals.at(i).x(),o.normals.at(i).y(),o.normals.at(i).z());\r
989             //glNormal3f(o.vertices.at(i).x(),o.vertices.at(i).y(),o.vertices.at(i).z());\r
990             glVertex3f(o.vertices.at(i).x(),o.vertices.at(i).y(),o.vertices.at(i).z());\r
991         }\r
992         glEnd();\r
993         glPopMatrix();\r
994     }\r
995     glPopAttrib();\r
996 }\r
997 \r
998 void DrawAxes(float zoomFactor)\r
999 {\r
1000     glPushAttrib(GL_ALL_ATTRIB_BITS);\r
1001     glDisable(GL_LIGHTING);\r
1002     glDisable(GL_TEXTURE_2D);\r
1003     glShadeModel (GL_FLAT);\r
1004     glDisable(GL_POINT_SPRITE);\r
1005 \r
1006     glEnable(GL_LINE_SMOOTH);\r
1007     glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);\r
1008     glEnable(GL_BLEND);\r
1009     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\r
1010 \r
1011     glDisable(GL_LINE_STIPPLE);\r
1012     glLineWidth(1.f);\r
1013     glLineStipple (1, 0xFFFF);\r
1014     glColor3f(0,0,0);\r
1015     float rad = 1.f*(zoomFactor/ZoomZero);\r
1016     glBegin(GL_LINES);\r
1017     glVertex3f(-rad, 0, 0);\r
1018     glVertex3f(+rad, 0, 0);\r
1019     glVertex3f(0, -rad, 0);\r
1020     glVertex3f(0, +rad, 0);\r
1021     glVertex3f(0, 0, -rad);\r
1022     glVertex3f(0, 0, +rad);\r
1023     glEnd();\r
1024 \r
1025     glEnable(GL_LINE_STIPPLE);\r
1026     glLineWidth(0.5f);\r
1027     glLineStipple (3, 0xAAAA);\r
1028     int steps = 10;\r
1029     FOR(i, steps-1)\r
1030     {\r
1031         glBegin(GL_LINES);\r
1032         glVertex3f(-rad, rad*(i+1)/steps, 0);\r
1033         glVertex3f(+rad, rad*(i+1)/steps, 0);\r
1034         glVertex3f(rad*(i+1)/steps, -rad, 0);\r
1035         glVertex3f(rad*(i+1)/steps, +rad, 0);\r
1036         glVertex3f(-rad, 0, rad*(i+1)/steps);\r
1037         glVertex3f(+rad, 0, rad*(i+1)/steps);\r
1038         glVertex3f(0, -rad, rad*(i+1)/steps);\r
1039         glVertex3f(0, +rad, rad*(i+1)/steps);\r
1040         glVertex3f(0, rad*(i+1)/steps, -rad);\r
1041         glVertex3f(0, rad*(i+1)/steps, +rad);\r
1042         glVertex3f(rad*(i+1)/steps, 0, -rad);\r
1043         glVertex3f(rad*(i+1)/steps, 0, +rad);\r
1044 \r
1045         glVertex3f(-rad, -rad*(i+1)/steps, 0);\r
1046         glVertex3f(+rad, -rad*(i+1)/steps, 0);\r
1047         glVertex3f(-rad*(i+1)/steps, -rad, 0);\r
1048         glVertex3f(-rad*(i+1)/steps, +rad, 0);\r
1049         glVertex3f(-rad, 0, -rad*(i+1)/steps);\r
1050         glVertex3f(+rad, 0, -rad*(i+1)/steps);\r
1051         glVertex3f(0, -rad, -rad*(i+1)/steps);\r
1052         glVertex3f(0, +rad, -rad*(i+1)/steps);\r
1053         glVertex3f(0, -rad*(i+1)/steps, -rad);\r
1054         glVertex3f(0, -rad*(i+1)/steps, +rad);\r
1055         glVertex3f(-rad*(i+1)/steps, 0, -rad);\r
1056         glVertex3f(-rad*(i+1)/steps, 0, +rad);\r
1057         glEnd();\r
1058     }\r
1059     glPopAttrib();\r
1060 }\r
1061 \r
1062 void DrawLights(std::vector<GLLight> &lights)\r
1063 {\r
1064     // we draw the lights\r
1065     glPushAttrib(GL_ALL_ATTRIB_BITS);\r
1066     glDisable(GL_LIGHTING);\r
1067     glDisable(GL_TEXTURE_2D);\r
1068     FOR(i, lights.size())\r
1069     {\r
1070         glPushMatrix();\r
1071         glTranslatef(lights[i].position[0],lights[i].position[1],lights[i].position[2]);\r
1072         glColor3f(0,0,1.0);\r
1073         DrawStandardSphere(0.05f);\r
1074         glPopMatrix();\r
1075     }\r
1076     glPopAttrib();\r
1077 }\r
1078 \r
1079 float angle = 0;\r
1080 void GLWidget::paintGL()\r
1081 {\r
1082     if(!canvas) return;\r
1083     mutex->lock();\r
1084     killObjects();\r
1085     generateObjects();\r
1086 \r
1087     modelViewMatrix.setToIdentity();\r
1088     modelViewMatrix.rotate(xRot / 16.0, 1.0, 0.0, 0.0);\r
1089     modelViewMatrix.rotate(yRot / 16.0, 0.0, 1.0, 0.0);\r
1090     modelViewMatrix.rotate(zRot / 16.0, 0.0, 0.0, 1.0);\r
1091     modelViewMatrix.translate(xPos, yPos, zPos);\r
1092 \r
1093     bool bHasReward = false;\r
1094     if(!objects.size())\r
1095     {\r
1096         glClearColor(1,1,1,1);\r
1097         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\r
1098         mutex->unlock();\r
1099         return;\r
1100     }\r
1101     FOR(i, objects.size())\r
1102     {\r
1103         if(objects[i].objectType.contains("Reward"))\r
1104         {\r
1105             bHasReward = true;\r
1106             break;\r
1107         }\r
1108     }\r
1109     if(bHasReward)\r
1110     {\r
1111         lights[0].position[0] = -5;\r
1112         lights[0].position[1] = 0;\r
1113         lights[0].position[2] = -5;\r
1114         lights[1].position[0] = 5;\r
1115         lights[1].position[1] = 5;\r
1116         lights[1].position[2] = -5;\r
1117     }\r
1118     else\r
1119     {\r
1120         lights[0].position[0] = 2*sin(angle*0.1f);\r
1121         lights[0].position[1] = 0;\r
1122         lights[0].position[2] = 2*cos(angle*0.1f);\r
1123         lights[1].position[0] = 2*sin(angle*0.13f);\r
1124         lights[1].position[1] = -2*cos(angle*0.13f);\r
1125         lights[1].position[2] = 2*sin(angle*0.13f);\r
1126         angle += 0.1f;\r
1127     }\r
1128 \r
1129     modelViewProjectionMatrix = perspectiveMatrix*modelViewMatrix;\r
1130     normalMatrix = modelViewMatrix.normalMatrix();\r
1131 \r
1132     // currently broken in windows (crashes for some reason every now and then)\r
1133     //RenderShadowMap(light_fbo, lights[0], objects);\r
1134     bool bDisplayShadowMap = false;\r
1135     if (bDisplayShadowMap)\r
1136     {\r
1137         QPixmap pixmap = QPixmap::fromImage(light_fbo->toImage());\r
1138         if(!lightLabel)\r
1139         {\r
1140             lightLabel = new QLabel();\r
1141             lightLabel->setScaledContents(true);\r
1142         }\r
1143         lightLabel->setPixmap(pixmap);\r
1144         lightLabel->show();\r
1145         lightLabel->repaint();\r
1146     }\r
1147 \r
1148     render_fbo->bind();\r
1149     checkGL();\r
1150     glEnable(GL_MULTISAMPLE);\r
1151     glClearColor(1.f, 1.f, 1.f, 1.0f);\r
1152     //  glClearColor(.5f, .5f, .5f, 1.0f);\r
1153     glClearStencil(0);\r
1154     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);\r
1155 \r
1156     glPushMatrix();\r
1157 \r
1158     // we do the camera rotation once for 'standard' opengl geometry (lines etc)\r
1159     glRotated(xRot / 16.0, 1.0, 0.0, 0.0);\r
1160     glRotated(yRot / 16.0, 0.0, 1.0, 0.0);\r
1161     glRotated(zRot / 16.0, 0.0, 0.0, 1.0);\r
1162     glTranslatef(xPos, yPos, zPos);\r
1163 \r
1164     glPushAttrib(GL_ALL_ATTRIB_BITS);\r
1165     checkGL();\r
1166 \r
1167     bool bBlurry = false;\r
1168     if(bDisplayBlurry && bDisplayTransparency)\r
1169     {\r
1170         FOR(i, objects.size())\r
1171         {\r
1172             if(!objectAlive[i]) continue;\r
1173             if(objects[i].objectType.contains("Surface") && objects[i].style.contains("blurry"))\r
1174             {\r
1175                 bBlurry = true;\r
1176                 break;\r
1177             }\r
1178         }\r
1179         if(bBlurry)\r
1180         {\r
1181             // first we begin by drawing all our blurry surfaces\r
1182             glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE);\r
1183             //glDisable(GL_DEPTH_TEST);\r
1184             glEnable(GL_STENCIL_TEST);\r
1185             glStencilFunc(GL_ALWAYS, 1, 1);\r
1186             glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);\r
1187             checkGL();\r
1188             int blurAmount = 3;\r
1189             FOR(i, objects.size())\r
1190             {\r
1191                 if(!objectAlive[i]) continue;\r
1192                 if(objects[i].objectType.contains("Surface") && objects[i].style.contains("blurry"))\r
1193                 {\r
1194                     QStringList params = objects[i].style.split(",");\r
1195                     FOR(j, params.size())\r
1196                     {\r
1197                         if(params[j].contains("blurry:"))\r
1198                         {\r
1199                             QStringList p = params[j].split(":");\r
1200                             blurAmount = p[1].toFloat();\r
1201                             break;\r
1202                         }\r
1203                     }\r
1204                     DrawObject(objects[i]);\r
1205                 }\r
1206             }\r
1207             glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);\r
1208             glStencilFunc(GL_EQUAL, 1, 1);\r
1209             glStencilOp(GL_KEEP,GL_KEEP,GL_KEEP);\r
1210             checkGL();\r
1211 \r
1212             // then we draw all the stuff that is BEHIND the surfaces\r
1213             glDepthFunc(GL_GREATER);\r
1214 \r
1215             // Here we draw the axes lines\r
1216             if(canvas->bDisplayGrid) DrawAxes(zoomFactor);\r
1217             // DrawLights(lights);\r
1218             FOR(i, objects.size())\r
1219             {\r
1220                 if(!objectAlive[i]) continue;\r
1221                 if(objects[i].objectType.contains("Canvas"))\r
1222                 {\r
1223                     if(objects[i].objectType.contains("trajectories"))\r
1224                     {\r
1225                         if(canvas->bDisplayTrajectories) DrawObject(objects[i]);\r
1226                     }\r
1227                     else if(canvas->bDisplaySamples ||\r
1228                             (canvas->sampleColors.size() == canvas->data->GetCount() && canvas->bDisplayLearned))\r
1229                     {\r
1230                         // we check if we need to recolor the object\r
1231                         if(canvas->bDisplayLearned && canvas->sampleColors.size() == canvas->data->GetCount())\r
1232                         {\r
1233                             GLObject o = objects[i];\r
1234                             FOR(j, o.vertices.size())\r
1235                             {\r
1236                                 QColor c = canvas->sampleColors[j];\r
1237                                 o.colors[j] = QVector4D(c.redF(), c.greenF(), c.blueF(), 1);\r
1238                             }\r
1239                             DrawObject(o);\r
1240                         }\r
1241                         else DrawObject(objects[i]);\r
1242                     }\r
1243                 }\r
1244             }\r
1245             FOR(i, objects.size())\r
1246             {\r
1247                 if(!objectAlive[i]) continue;\r
1248                 if(objects[i].objectType.contains("Canvas")) continue;\r
1249                 if(objects[i].objectType.contains("Surface") && objects[i].style.contains("blurry")) continue;\r
1250                 DrawObject(objects[i]);\r
1251             }\r
1252             glDepthFunc(GL_LEQUAL);\r
1253 \r
1254             QGLShaderProgram *program = shaders["BlurFBO"];\r
1255             program->bind();\r
1256             program->setUniformValue("bVertical", 1);\r
1257             program->setUniformValue("amount", blurAmount);\r
1258             QRect rect(0, 0, render_fbo->width(), render_fbo->height());\r
1259             QGLFramebufferObject::blitFramebuffer(texture_fbo, rect, render_fbo, rect);\r
1260             RenderFBO(texture_fbo, program);\r
1261             QGLFramebufferObject::blitFramebuffer(texture_fbo, rect, render_fbo, rect);\r
1262             program->setUniformValue("bVertical", 0);\r
1263             RenderFBO(texture_fbo, program);\r
1264             program->release();\r
1265 \r
1266             glDisable(GL_STENCIL_TEST);\r
1267             FOR(i, objects.size())\r
1268             {\r
1269                 if(!objectAlive[i]) continue;\r
1270                 if(objects[i].objectType.contains("Surfaces") && objects[i].style.contains("blurry"))\r
1271                     DrawObject(objects[i]);\r
1272             }\r
1273         }\r
1274     }\r
1275 \r
1276     // Here we draw the axes lines\r
1277     if(canvas->bDisplayGrid) DrawAxes(zoomFactor);\r
1278     // DrawLights(lights);\r
1279 \r
1280     FOR(i, objects.size())\r
1281     {\r
1282         if(!objectAlive[i]) continue;\r
1283         if(objects[i].objectType.contains("Canvas"))\r
1284         {\r
1285             if(objects[i].objectType.contains("trajectories"))\r
1286             {\r
1287                 if(bDisplayLines) DrawObject(objects[i]);\r
1288             }\r
1289             else if(bDisplaySamples)\r
1290             {\r
1291                 // we check if we need to recolor the object\r
1292                 if(canvas->bDisplayLearned && canvas->sampleColors.size() == canvas->data->GetCount())\r
1293                 {\r
1294                     GLObject o = objects[i];\r
1295                     FOR(j, o.vertices.size())\r
1296                     {\r
1297                         QColor c = canvas->sampleColors[j];\r
1298                         o.colors[j] = QVector4D(c.redF(), c.greenF(), c.blueF(),1);\r
1299                     }\r
1300                     DrawObject(o);\r
1301                 }\r
1302                 else DrawObject(objects[i]);\r
1303             }\r
1304         }\r
1305     }\r
1306     FOR(i, objects.size())\r
1307     {\r
1308         if(!objectAlive[i]) continue;\r
1309         if(objects[i].objectType.contains("Canvas")) continue;\r
1310         if(bDisplayBlurry && bDisplayTransparency &&\r
1311                 objects[i].objectType.contains("Surface") &&\r
1312                 objects[i].style.contains("blurry")) continue;\r
1313         DrawObject(objects[i]);\r
1314     }\r
1315 \r
1316     glPopAttrib();\r
1317     glPushAttrib(GL_ALL_ATTRIB_BITS);\r
1318 \r
1319     if(bDisplaySamples)\r
1320     {\r
1321         // we begin with the sample sprites\r
1322         glEnable(GL_TEXTURE_2D);\r
1323         glBindTexture(GL_TEXTURE_2D, GLWidget::textureNames[0]);\r
1324         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);\r
1325         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);\r
1326         vector< pair<float, int> > list;\r
1327 \r
1328         // get gl matrices\r
1329         GLdouble modelMatrix[16];\r
1330         GLdouble projectionMatrix[16];\r
1331         glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix);\r
1332         glGetDoublev(GL_PROJECTION_MATRIX, projectionMatrix);\r
1333         MathLib::Matrix4 model;\r
1334         FOR(j, 4)\r
1335         {\r
1336             FOR(i, 4)\r
1337             {\r
1338                 model(i,j) = modelMatrix[j*4 + i];\r
1339             }\r
1340         }\r
1341 \r
1342         FOR(i, drawSampleLists.size())\r
1343         {\r
1344             if(drawSampleListCenters.count(drawSampleLists[i]))\r
1345             {\r
1346                 fvec mean = drawSampleListCenters[drawSampleLists[i]];\r
1347                 MathLib::Vector3 v(mean[0],mean[1],mean[2]);\r
1348                 MathLib::Vector3 vCam;\r
1349                 model.Transform(v, vCam);\r
1350                 list.push_back(make_pair(vCam(2), i));\r
1351             }\r
1352             else list.push_back(make_pair(-FLT_MAX, i));\r
1353         }\r
1354         std::sort(list.begin(), list.end());\r
1355 \r
1356         FOR(i, list.size())\r
1357         {\r
1358             glCallList(drawSampleLists[list[i].second]);\r
1359         }\r
1360 \r
1361         FOR(i, drawLists.size())\r
1362         {\r
1363             glCallList(drawLists[i]);\r
1364         }\r
1365     }\r
1366     glPopAttrib();\r
1367     glPopMatrix();\r
1368     render_fbo->release();\r
1369 \r
1370     if (render_fbo != texture_fbo) {\r
1371         QRect rect(0, 0, render_fbo->width(), render_fbo->height());\r
1372         QGLFramebufferObject::blitFramebuffer(texture_fbo, rect,\r
1373                                               render_fbo, rect);\r
1374     }\r
1375 \r
1376     QGLShaderProgram *program = shaders["RenderFBO"];\r
1377     program->bind();\r
1378     RenderFBO(texture_fbo, program);\r
1379     program->release();\r
1380     mutex->unlock();\r
1381 }\r
1382 \r
1383 void GLWidget::RenderShadowMap(QGLFramebufferObject *fbo, GLLight light, std::vector<GLObject> objects)\r
1384 {\r
1385     if(!fbo || !objects.size()) return;\r
1386 \r
1387     //glMatrixMode(GL_PROJECTION);\r
1388     //glPushMatrix();\r
1389     //glMatrixMode(GL_MODELVIEW);\r
1390     //glPushMatrix();\r
1391     //glViewport(0,0,512,512);\r
1392 \r
1393     fbo->bind();\r
1394     glEnable(GL_MULTISAMPLE);\r
1395     glClearColor(1.f, 1.f, 1.f, 1.0f);\r
1396     //    glClearColor(.5f, .5f, .5f, 1.0f);\r
1397     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);\r
1398 \r
1399 \r
1400     double zNear = 1.0;\r
1401     double zFar = 60.0;\r
1402 \r
1403     QVector3D lightUp(0,1,0);\r
1404     QVector3D lightPos(light.position[0], light.position[1], light.position[2]);\r
1405     lightMvMatrix.setToIdentity();\r
1406     //    mvMatrix.lookAt(QVector3D(0,0,-40), QVector3D(0,0,0), lightUp);\r
1407     lightMvMatrix.lookAt(lightPos, QVector3D(0,0,0), lightUp);\r
1408     lightPMatrix.setToIdentity();\r
1409     lightPMatrix.perspective(90.,1.,zNear,zFar);\r
1410 \r
1411     lightMvpMatrix = lightPMatrix * lightMvMatrix;\r
1412     QMatrix3x3 nMatrix = lightMvMatrix.normalMatrix();\r
1413 \r
1414     glPushAttrib(GL_ALL_ATTRIB_BITS);\r
1415     FOR(i, objects.size())\r
1416     {\r
1417 \r
1418         GLObject& o = objects[i];\r
1419         if(!o.vertices.size()) continue;\r
1420         QString style = o.style.toLower();\r
1421         if(style.contains("transparent")) continue;\r
1422         float pointSize = 12.f;\r
1423         if(style.contains("pointsize"))\r
1424         {\r
1425             QStringList params = style.split(",");\r
1426             FOR(i, params.size())\r
1427             {\r
1428                 if(params[i].contains("pointsize"))\r
1429                 {\r
1430                     QStringList p = params[i].split(":");\r
1431                     pointSize = p.at(1).toFloat();\r
1432                     break;\r
1433                 }\r
1434             }\r
1435         }\r
1436 \r
1437         QGLShaderProgram *program = shaders["DepthSamples"];\r
1438         program->bind();\r
1439         program->enableAttributeArray(0);\r
1440         program->setAttributeArray(0, o.vertices.constData());\r
1441         program->setUniformValue("mvpMatrix", lightMvpMatrix);\r
1442         program->setUniformValue("mvmatrix", lightMvMatrix);\r
1443 \r
1444         glPushAttrib(GL_ALL_ATTRIB_BITS);\r
1445         glDisable(GL_LIGHTING);\r
1446         glEnable(GL_DEPTH_TEST);\r
1447         glDepthMask(GL_TRUE);\r
1448         glDisable(GL_BLEND);\r
1449         glEnable(GL_ALPHA_TEST);\r
1450         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\r
1451 \r
1452         glEnable(GL_TEXTURE_2D);\r
1453         glEnable(GL_POINT_SPRITE);\r
1454         if(o.style.contains("rings")) glBindTexture(GL_TEXTURE_2D, GLWidget::textureNames[1]);\r
1455         else glBindTexture(GL_TEXTURE_2D, GLWidget::textureNames[0]);\r
1456         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);\r
1457         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);\r
1458         program->setUniformValue("color_texture", 0);\r
1459         glEnable(GL_PROGRAM_POINT_SIZE_EXT);\r
1460         glPointSize(pointSize);\r
1461 \r
1462         // we actually draw stuff!\r
1463         glDrawArrays(GL_POINTS,0,o.vertices.size());\r
1464         glPopAttrib();\r
1465         program->release();\r
1466     }\r
1467     glPopAttrib();\r
1468 \r
1469     // we blur the shadowmap\r
1470     QGLShaderProgram *program = shaders["BlurFBO"];\r
1471     program->bind();\r
1472     program->setUniformValue("bVertical", 1);\r
1473     program->setUniformValue("amount", 7);\r
1474     QRect rect(0, 0, light_fbo->width(), light_fbo->height());\r
1475     QGLFramebufferObject::blitFramebuffer(lightBlur_fbo, rect, light_fbo, rect);\r
1476     RenderFBO(lightBlur_fbo, program);\r
1477     QGLFramebufferObject::blitFramebuffer(lightBlur_fbo, rect, light_fbo, rect);\r
1478     program->setUniformValue("bVertical", 0);\r
1479     RenderFBO(lightBlur_fbo, program);\r
1480     program->release();\r
1481     fbo->release();\r
1482 \r
1483     //glMatrixMode(GL_PROJECTION);\r
1484     //glPopMatrix();\r
1485     //glMatrixMode(GL_MODELVIEW);\r
1486     //glPopMatrix();\r
1487     //glViewport(0,0,width,height);\r
1488 }\r
1489 \r
1490 \r
1491 void GLWidget::RenderFBO(QGLFramebufferObject *fbo, QGLShaderProgram *program)\r
1492 {\r
1493     if(!fbo || !program) return;\r
1494     // save GL state\r
1495     glPushAttrib(GL_ALL_ATTRIB_BITS);\r
1496     glMatrixMode(GL_PROJECTION);\r
1497     glPushMatrix();\r
1498     glMatrixMode(GL_MODELVIEW);\r
1499     glPushMatrix();\r
1500 \r
1501     // set ortho view\r
1502     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\r
1503     glMatrixMode(GL_PROJECTION);\r
1504     glLoadIdentity();\r
1505     glOrtho(0.0, width, 0.0, height, -1.0, 1.0);\r
1506     glMatrixMode(GL_MODELVIEW);\r
1507     glLoadIdentity();\r
1508     glDisable(GL_LIGHTING);\r
1509     glDisable(GL_DEPTH_TEST);\r
1510     glDisable(GL_STENCIL_TEST);\r
1511 \r
1512     program->setUniformValue("texture", 0);\r
1513     GLfloat fbo_vertices[] = {\r
1514         -1, -1,\r
1515         1, -1,\r
1516         -1,  1,\r
1517         1,  1,\r
1518     };\r
1519     program->enableAttributeArray(0);\r
1520     program->setAttributeArray(0,fbo_vertices,2);\r
1521 \r
1522     // we bind the texture\r
1523     glBindTexture(GL_TEXTURE_2D, fbo->texture());\r
1524     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);\r
1525     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);\r
1526     glEnable(GL_TEXTURE_2D);\r
1527     glEnable(GL_MULTISAMPLE);\r
1528 \r
1529     glDrawArrays(GL_TRIANGLE_STRIP,0,4);\r
1530 \r
1531     // restore GL state\r
1532     glMatrixMode(GL_PROJECTION);\r
1533     glPopMatrix();\r
1534     glMatrixMode(GL_MODELVIEW);\r
1535     glPopMatrix();\r
1536     glPopAttrib();\r
1537 }\r
1538 \r
1539 void GLWidget::zoom(int delta)\r
1540 {\r
1541     if(delta > 0)\r
1542     {\r
1543         zoomFactor *= 0.9;\r
1544     }\r
1545     else\r
1546     {\r
1547         zoomFactor *= 1.1;\r
1548     }\r
1549     qDebug() << "zoomFactor" << zoomFactor;\r
1550     resizeGL(width, height);\r
1551     repaint();\r
1552 }\r
1553 \r
1554 void GLWidget::resizeGL(int width, int height)\r
1555 {\r
1556     this->width = width;\r
1557     this->height = height;\r
1558 \r
1559     glViewport(0,0,width, height);\r
1560     viewport = QVector4D(0,0,width,height);\r
1561     float ratio = width/(float)height;\r
1562 \r
1563     glMatrixMode(GL_PROJECTION);\r
1564     glLoadIdentity();\r
1565     double left = -ratio, right = ratio, bottom = -1.0, top = 1.0;\r
1566     double zNear = 1.0;\r
1567     double zFar = 60.0;\r
1568     glFrustum(left*zoomFactor, right*zoomFactor,\r
1569               bottom*zoomFactor, top*zoomFactor, zNear, zFar);\r
1570     glMatrixMode(GL_MODELVIEW);\r
1571     glLoadIdentity();\r
1572     glTranslated(0.0, 0.0, -40.0);\r
1573 \r
1574     perspectiveMatrix.setToIdentity();\r
1575     perspectiveMatrix.frustum(left*zoomFactor, right*zoomFactor,\r
1576                               bottom*zoomFactor, top*zoomFactor, zNear, zFar);\r
1577     perspectiveMatrix.translate(0,0,-40);\r
1578     if(width != render_fbo->width() && height != render_fbo->height())\r
1579     {\r
1580         if(render_fbo->isBound())render_fbo->release();\r
1581         //if(texture_fbo && texture_fbo != render_fbo) delete texture_fbo;\r
1582         delete render_fbo;\r
1583         delete light_fbo;\r
1584         delete lightBlur_fbo;\r
1585         if (QGLFramebufferObject::hasOpenGLFramebufferBlit()) {\r
1586             QGLFramebufferObjectFormat format;\r
1587             format.setSamples(64);\r
1588             format.setAttachment(QGLFramebufferObject::CombinedDepthStencil);\r
1589             render_fbo = new QGLFramebufferObject(width, height, format);\r
1590             texture_fbo = new QGLFramebufferObject(width, height);\r
1591         } else {\r
1592             render_fbo = new QGLFramebufferObject(width*2, height*2);\r
1593             texture_fbo = render_fbo;\r
1594         }\r
1595         QGLFramebufferObjectFormat format;\r
1596         format.setAttachment(QGLFramebufferObject::CombinedDepthStencil);\r
1597         light_fbo = new QGLFramebufferObject(width,height, format);\r
1598         lightBlur_fbo = new QGLFramebufferObject(width,height);\r
1599     }\r
1600 }\r
1601 \r
1602 void GLWidget::mousePressEvent(QMouseEvent *event)\r
1603 {\r
1604     lastPos = event->pos();\r
1605 }\r
1606 \r
1607 void GLWidget::mouseMoveEvent(QMouseEvent *event)\r
1608 {\r
1609     int dx = event->x() - lastPos.x();\r
1610     int dy = event->y() - lastPos.y();\r
1611 \r
1612     if (event->modifiers() & Qt::ShiftModifier)\r
1613     {\r
1614         if(event->buttons() & Qt::LeftButton)\r
1615         {\r
1616             setXPosition(xPos + -dy/64.f*sin(yRot));\r
1617             setZPosition(zPos + -dx/64.f*(-cos(yRot)));\r
1618         }\r
1619         else if(event->buttons() & Qt::RightButton)\r
1620         {\r
1621             setYPosition(yPos - dy/64.f);\r
1622         }\r
1623     }\r
1624     else\r
1625     {\r
1626         if (event->buttons() & Qt::LeftButton) {\r
1627             setXRotation(xRot + 8 * dy);\r
1628             setYRotation(yRot + 8 * dx);\r
1629         } else if (event->buttons() & Qt::RightButton) {\r
1630             //setXRotation(xRot + 8 * dy);\r
1631             //setZRotation(zRot + 8 * dx);\r
1632         }\r
1633     }\r
1634     lastPos = event->pos();\r
1635 }\r
1636 \r
1637 void GLWidget::wheelEvent(QWheelEvent *event)\r
1638 {\r
1639     zoom(event->delta());\r
1640 }\r
1641 \r
1642 void GLWidget::resizeEvent(QResizeEvent *event)\r
1643 {\r
1644     resizeGL(event->size().width(), event->size().height());\r
1645 }\r
1646 \r
1647 void GLWidget::normalizeAngle(int *angle)\r
1648 {\r
1649     while (*angle < 0)\r
1650         *angle += 360 * 16;\r
1651     while (*angle > 360 * 16)\r
1652         *angle -= 360 * 16;\r
1653 }\r
1654 \r
1655 GLuint *GLWidget::textureNames = new GLuint[textureCount];\r
1656 unsigned char **GLWidget::textureData = 0;\r
1657 \r
1658 void GLWidget::LoadShader(QGLShaderProgram **program_, QString vshader, QString fshader)\r
1659 {\r
1660     QGLShaderProgram *program = *program_;\r
1661     if(program)\r
1662     {\r
1663         program->release();\r
1664         QList<QGLShader*> shaders = program->shaders();\r
1665         FOR(i, shaders.size())\r
1666         {\r
1667             delete shaders.at(i);\r
1668         }\r
1669         program->removeAllShaders();\r
1670     }\r
1671     else program = new QGLShaderProgram;\r
1672     QGLShader *VertexShader = NULL, *FragmentShader = NULL;\r
1673 \r
1674     // load and compile vertex shader\r
1675     QFileInfo vsh(vshader);\r
1676     if(vsh.exists())\r
1677     {\r
1678         VertexShader = new QGLShader(QGLShader::Vertex);\r
1679         if(VertexShader->compileSourceFile(vshader))\r
1680             program->addShader(VertexShader);\r
1681         else qWarning() << "Vertex Shader Error" << VertexShader->log();\r
1682     }\r
1683     else qWarning() << "Vertex Shader source file " << vshader << " not found.";\r
1684 \r
1685     // load and compile fragment shader\r
1686     QFileInfo fsh(fshader);\r
1687     if(fsh.exists())\r
1688     {\r
1689         FragmentShader = new QGLShader(QGLShader::Fragment);\r
1690         if(FragmentShader->compileSourceFile(fshader))\r
1691             program->addShader(FragmentShader);\r
1692         else qWarning() << "Fragment Shader Error" << FragmentShader->log();\r
1693     }\r
1694     else qWarning() << "Fragment Shader source file " << fshader << " not found.";\r
1695 \r
1696     if(!program->link())\r
1697     {\r
1698         qWarning() << "Shader Program Linker Error" << program->log();\r
1699     }\r
1700     else program->bind();\r
1701     program->release();\r
1702     *program_ = program;\r
1703 }\r
1704 \r
1705 \r
1706 void GLWidget::setXPosition(float pos)\r
1707 {\r
1708     if (pos != xPos) {\r
1709         xPos = pos;\r
1710         emit xPositionChanged(pos);\r
1711         updateGL();\r
1712     }\r
1713 }\r
1714 \r
1715 void GLWidget::setYPosition(float pos)\r
1716 {\r
1717     if (pos != yPos) {\r
1718         yPos = pos;\r
1719         emit yPositionChanged(pos);\r
1720         updateGL();\r
1721     }\r
1722 }\r
1723 \r
1724 void GLWidget::setZPosition(float pos)\r
1725 {\r
1726     if (pos != zPos) {\r
1727         zPos = pos;\r
1728         emit zPositionChanged(pos);\r
1729         updateGL();\r
1730     }\r
1731 }\r
1732 \r
1733 void GLWidget::setXRotation(int angle)\r
1734 {\r
1735     normalizeAngle(&angle);\r
1736     if (angle != xRot) {\r
1737         xRot = angle;\r
1738         emit xRotationChanged(angle);\r
1739         updateGL();\r
1740     }\r
1741 }\r
1742 \r
1743 void GLWidget::setYRotation(int angle)\r
1744 {\r
1745     normalizeAngle(&angle);\r
1746     if (angle != yRot) {\r
1747         yRot = angle;\r
1748         emit yRotationChanged(angle);\r
1749         updateGL();\r
1750     }\r
1751 }\r
1752 \r
1753 void GLWidget::setZRotation(int angle)\r
1754 {\r
1755     normalizeAngle(&angle);\r
1756     if (angle != zRot) {\r
1757         zRot = angle;\r
1758         emit zRotationChanged(angle);\r
1759         updateGL();\r
1760     }\r
1761 }\r