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