MNE-CPP  beta 1.0
inverseview.cpp
Go to the documentation of this file.
1 //=============================================================================================================
37 //*************************************************************************************************************
38 //=============================================================================================================
39 // INCLUDES
40 //=============================================================================================================
41 
42 #include "inverseview.h"
43 #include "inverseviewproducer.h"
44 
45 #include <fs/label.h>
46 #include <disp/colormap.h>
47 
48 
49 //*************************************************************************************************************
50 //=============================================================================================================
51 // Qt INCLUDES
52 //=============================================================================================================
53 
54 #include "qglbuilder.h"
55 #include "qglcube.h"
56 
57 #include <QtCore/qurl.h>
58 #include <QArray>
59 #include <QTimer>
60 #include <QMouseEvent>
61 
62 
63 //*************************************************************************************************************
64 //=============================================================================================================
65 // STL INCLUDES
66 //=============================================================================================================
67 
68 #include <iostream>
69 
70 
71 //*************************************************************************************************************
72 //=============================================================================================================
73 // USED NAMESPACES
74 //=============================================================================================================
75 
76 using namespace DISP3DLIB;
77 using namespace DISPLIB;
78 
79 
80 //*************************************************************************************************************
81 //=============================================================================================================
82 // DEFINE MEMBER METHODS
83 //=============================================================================================================
84 
85 InverseView::InverseView(const MNESourceSpace &p_sourceSpace, QList<Label> &p_qListLabels, QList<RowVector4i> &p_qListRGBAs, qint32 p_iFps, bool p_bLoop, bool p_bStereo, bool p_bSlowMotion, QWindow *parent)
86 : QGLView(parent)
87 , m_pInverseViewProducer(new InverseViewProducer(p_iFps, p_bLoop, p_bSlowMotion))
88 , m_sourceSpace(p_sourceSpace)
89 , m_qListLabels(p_qListLabels)
90 , m_qListRGBAs(p_qListRGBAs)
91 , m_iColorMode(0)
92 , m_bStereo(p_bStereo)
93 , m_fOffsetZ(-100.0f)
94 , m_fOffsetZEye(60.0f)
95 , m_pSceneNodeBrain(0)
96 , m_pSceneNode(0)
97 {
98  qRegisterMetaType<QSharedPointer<Eigen::VectorXd> >("QSharedPointer<Eigen::VectorXd>");
99 
100 
101 // m_pCameraFrontal = new QGLCamera(this);
102 // m_pCameraFrontal->setAdjustForAspectRatio(false);
103 
104 // qDebug() << "p_qListLabels" << p_qListLabels.size();
105 
106  QObject::connect(m_pInverseViewProducer.data(), &InverseViewProducer::sourceEstimateSample, this, &InverseView::updateActivation);
107 }
108 
109 
110 //*************************************************************************************************************
111 
113 {
114  m_pInverseViewProducer->stop();
115 
116  delete m_pSceneNode;
117 }
118 
119 
120 //*************************************************************************************************************
121 
123 {
124  m_pInverseViewProducer->pushSourceEstimate(p_sourceEstimate);
125 }
126 
127 
128 //*************************************************************************************************************
129 
130 void InverseView::initializeGL(QGLPainter *painter)
131 {
132  // in the constructor construct a builder on the stack
133  QGLBuilder builder;
134 
135  float fac = 100.0f; // too small vertices distances cause clipping errors --> 100 is a good value for freesurfer brain measures
136 
137  builder << QGL::Faceted;
138  m_pSceneNodeBrain = builder.currentNode();
139 
140  builder.pushNode();
141 
142  // Collor palette
143  qint32 index;
144  QSharedPointer<QGLMaterialCollection> palette = builder.sceneNode()->palette(); // register color palette within the root node
145 
146  m_qListMapLabelIdIndex << QMap<qint32, qint32>() << QMap<qint32, qint32>();
147 
148  //get bounding box
149  m_vecBoundingBoxMin.setX(m_sourceSpace[0].rr.col(0).minCoeff()); // X lh min
150  m_vecBoundingBoxMin.setY(m_sourceSpace[0].rr.col(1).minCoeff()); // Y lh min
151  m_vecBoundingBoxMin.setZ(m_sourceSpace[0].rr.col(2).minCoeff()); // Z lh min
152  m_vecBoundingBoxMax.setX(m_sourceSpace[0].rr.col(0).maxCoeff()); // X lh max
153  m_vecBoundingBoxMax.setY(m_sourceSpace[0].rr.col(1).maxCoeff()); // Y lh max
154  m_vecBoundingBoxMax.setZ(m_sourceSpace[0].rr.col(2).maxCoeff()); // Z lh max
155 
156  m_vecBoundingBoxMin.setX(m_vecBoundingBoxMin.x() < m_sourceSpace[1].rr.col(0).minCoeff() ? m_vecBoundingBoxMin.x() : m_sourceSpace[1].rr.col(0).minCoeff()); // X rh min
157  m_vecBoundingBoxMin.setY(m_vecBoundingBoxMin.y() < m_sourceSpace[1].rr.col(1).minCoeff() ? m_vecBoundingBoxMin.y() : m_sourceSpace[1].rr.col(1).minCoeff()); // Y rh min
158  m_vecBoundingBoxMin.setZ(m_vecBoundingBoxMin.z() < m_sourceSpace[1].rr.col(2).minCoeff() ? m_vecBoundingBoxMin.z() : m_sourceSpace[1].rr.col(2).minCoeff()); // Z rh min
159  m_vecBoundingBoxMax.setX(m_vecBoundingBoxMax.x() > m_sourceSpace[1].rr.col(0).maxCoeff() ? m_vecBoundingBoxMax.x() : m_sourceSpace[1].rr.col(0).maxCoeff()); // X rh max
160  m_vecBoundingBoxMax.setY(m_vecBoundingBoxMax.y() > m_sourceSpace[1].rr.col(1).maxCoeff() ? m_vecBoundingBoxMax.y() : m_sourceSpace[1].rr.col(1).maxCoeff()); // Y rh max
161  m_vecBoundingBoxMax.setZ(m_vecBoundingBoxMax.z() > m_sourceSpace[1].rr.col(2).maxCoeff() ? m_vecBoundingBoxMax.z() : m_sourceSpace[1].rr.col(2).maxCoeff()); // Z rh max
162 
163  m_vecBoundingBoxCenter.setX((m_vecBoundingBoxMin.x()+m_vecBoundingBoxMax.x())/2.0f);
164  m_vecBoundingBoxCenter.setY((m_vecBoundingBoxMin.y()+m_vecBoundingBoxMax.y())/2.0f);
165  m_vecBoundingBoxCenter.setZ((m_vecBoundingBoxMin.z()+m_vecBoundingBoxMax.z())/2.0f);
166 
167 
168  //
169  // Build each hemisphere in its separate node
170  //
171  for(qint32 h = 0; h < 2; ++h)
172  {
173  builder.newNode();//create new hemisphere node
174  {
175  MatrixX3i tris;
176  MatrixX3f rr = m_sourceSpace[h].rr;
177 
178  //Centralize
179  rr.col(0) = rr.col(0).array() - m_vecBoundingBoxCenter.x();
180  rr.col(1) = rr.col(1).array() - m_vecBoundingBoxCenter.y();
181  rr.col(2) = rr.col(2).array() - m_vecBoundingBoxCenter.z();
182 
183  builder.pushNode();
184  //
185  // Create each ROI in its own node
186  //
187  for(qint32 k = 0; k < m_qListLabels.size(); ++k)
188  {
189  //check if label hemi fits current hemi
190  if(m_qListLabels[k].hemi != h)
191  continue;
192 
193  //Ggenerate label tri information
194  tris = m_qListLabels[k].selectTris(m_sourceSpace[h].tris);
195 
196  // add new ROI node when current ROI node is not empty
197  if(builder.currentNode()->count() > 0)
198  builder.newNode();
199 
200 
201  QGeometryData t_GeometryDataTri;
202 
203 
204  MatrixXf t_TriCoords(3,3*tris.rows());
205 
206  for(qint32 i = 0; i < tris.rows(); ++i)
207  {
208  t_TriCoords.col(i*3) = rr.row( tris(i,0) ).transpose();
209  t_TriCoords.col(i*3+1) = rr.row( tris(i,1) ).transpose();
210  t_TriCoords.col(i*3+2) = rr.row( tris(i,2) ).transpose();
211  }
212 
213  t_TriCoords *= fac;
214  t_GeometryDataTri.appendVertexArray(QArray<QVector3D>::fromRawData( reinterpret_cast<const QVector3D*>(t_TriCoords.data()), t_TriCoords.cols() ));
215 
216  //
217  // If triangles are available.
218  //
219  if (t_GeometryDataTri.count() > 0)
220  {
221 
222  //
223  // Add triangles to current node
224  //
225  builder.addTriangles(t_GeometryDataTri);
226 
227  //
228  // Colorize ROI
229  //
230  QGLMaterial *t_pMaterialROI = new QGLMaterial();
231  int r, g, b;
232 
233  if(m_iColorMode == 0)
234  {
235  r = 100;
236  g = 100;
237  b = 100;
238  }
239  else if(m_iColorMode == 1)
240  {
241  r = m_qListRGBAs[k][0];
242  g = m_qListRGBAs[k][1];
243  b = m_qListRGBAs[k][2];
244  }
245 
246 // t_pMaterialROI->setColor(QColor(r,g,b,200));
247  t_pMaterialROI->setColor(QColor(r,g,b,230));
248 // t_pMaterialROI->setEmittedLight(QColor(100,100,100,255));
249 // t_pMaterialROI->setSpecularColor(QColor(10,10,10,20));
250 
251  index = palette->addMaterial(t_pMaterialROI);
252  builder.currentNode()->setMaterialIndex(index);
253 
254  m_qListMapLabelIdIndex[h].insert(m_qListLabels[k].label_id, index);
255  }
256  }
257  }
258  // Go one level up
259  builder.popNode();
260  }
261  // Go one level up
262  builder.popNode();
263 
264  // Optimze current scene for display and calculate lightning normals
265  m_pSceneNode = builder.finalizedSceneNode();
266  m_pSceneNode->setParent(this);
267 
268  //
269  // Create light models
270  //
271  m_pLightModel = new QGLLightModel(this);
272  m_pLightModel->setAmbientSceneColor(Qt::white);
273  m_pLightModel->setViewerPosition(QGLLightModel::LocalViewer);
274 
275  m_pLightModel = new QGLLightModel(this);
276 
277  m_pLightParametersScene = new QGLLightParameters(this);
278  m_pLightParametersScene->setPosition(QVector3D(0.0f, 0.0f, 3.0f));
279  painter->setMainLight(m_pLightParametersScene);
280 
281  //
282  // Set stereo type
283  //
284  if (m_bStereo) {
285 // this->setStereoType(QGLView::RedCyanAnaglyph);
286  this->setStereoType(QGLView::StretchedLeftRight);
287 // camera()->setEyeSeparation(0.4f);
288 // m_pCameraFrontal->setEyeSeparation(0.1f);
289 
290  //LNdT DEMO
291  camera()->setCenter(QVector3D(0,0,m_fOffsetZ));//0.8f*fac));
292  camera()->setEyeSeparation(0.4f);
293  camera()->setFieldOfView(30);
294  camera()->setEye(QVector3D(0,0,m_fOffsetZEye));
295  //LNdT DEMO end
296 
297  }
298 
299 // //set background to light grey-blue
300 // glClearColor(0.8f, 0.8f, 1.0f, 0.0f);
301 
302 // //set background to light white
303  glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
304 
305  //start the producer
306  m_pInverseViewProducer->start();
307 }
308 
309 
310 //*************************************************************************************************************
311 
312 void InverseView::paintGL(QGLPainter *painter)
313 {
314  glEnable(GL_BLEND); // enable transparency
315 
316  // painter->modelViewMatrix().rotate(45.0f, 1.0f, 1.0f, 1.0f);
317 
318 
319  painter->modelViewMatrix().push();
320  painter->projectionMatrix().push();
321 
322  painter->setStandardEffect(QGL::LitMaterial);
323 // painter->setCamera(m_pCameraFrontal);
324  painter->setLightModel(m_pLightModel);
325 
326 // material.bind(painter);
327 // material.prepareToDraw(painter, painter->attributes());
328 
329  m_pSceneNode->draw(painter);
330 
331 
332  painter->modelViewMatrix().pop();
333  painter->projectionMatrix().pop();
334 }
335 
336 
337 //*************************************************************************************************************
338 
339 void InverseView::keyPressEvent(QKeyEvent *e)
340 {
341  camera()->setCenter(QVector3D(0,0,0));
342 
343  float normEyeOld = sqrt(pow(camera()->eye().x(),2) + pow(camera()->eye().y(),2) + pow(camera()->eye().z(),2));
344 
345  QGLView::keyPressEvent(e);
346 
347  float dx = (camera()->eye().x()*m_fOffsetZ)/m_fOffsetZEye;
348  float dy = (camera()->eye().y()*m_fOffsetZ)/m_fOffsetZEye;
349  float dz = (camera()->eye().z()*m_fOffsetZ)/m_fOffsetZEye;
350 
351  float normEye = sqrt(pow(camera()->eye().x(),2) + pow(camera()->eye().y(),2) + pow(camera()->eye().z(),2));
352  float scaleEye = normEyeOld/normEye;//m_fOffsetZEye/normEye;
353  camera()->setEye(QVector3D(camera()->eye().x()*scaleEye,camera()->eye().y()*scaleEye,camera()->eye().z()*scaleEye));
354 
355  camera()->setCenter(QVector3D(dx,dy,dz));
356 }
357 
358 
359 //*************************************************************************************************************
360 
361 void InverseView::mouseMoveEvent(QMouseEvent *e)
362 {
363  camera()->setCenter(QVector3D(0,0,0));
364 
365  float normEyeOld = sqrt(pow(camera()->eye().x(),2) + pow(camera()->eye().y(),2) + pow(camera()->eye().z(),2));
366 
367  QGLView::mouseMoveEvent(e);
368 
369  float dx = (camera()->eye().x()*m_fOffsetZ)/m_fOffsetZEye;
370  float dy = (camera()->eye().y()*m_fOffsetZ)/m_fOffsetZEye;
371  float dz = (camera()->eye().z()*m_fOffsetZ)/m_fOffsetZEye;
372 
373  float normEye = sqrt(pow(camera()->eye().x(),2) + pow(camera()->eye().y(),2) + pow(camera()->eye().z(),2));
374  float scaleEye = normEyeOld/normEye;//m_fOffsetZEye/normEye;
375  camera()->setEye(QVector3D(camera()->eye().x()*scaleEye,camera()->eye().y()*scaleEye,camera()->eye().z()*scaleEye));
376 
377  camera()->setCenter(QVector3D(dx,dy,dz));
378 }
379 
380 
381 //*************************************************************************************************************
382 
383 void InverseView::mousePressEvent(QMouseEvent *e)
384 {
385 
386  if(e->buttons() & Qt::RightButton)
387  {
388  float normEye = sqrt(pow(camera()->eye().x(),2) + pow(camera()->eye().y(),2) + pow(camera()->eye().z(),2));
389  camera()->setCenter(QVector3D(0,0,m_fOffsetZ));
390  camera()->setEye(QVector3D(0,0,normEye));
391  }
392 
393  QGLView::mousePressEvent(e);
394 }
395 
396 
397 
398 //*************************************************************************************************************
399 
400 //QGLSceneNode *InverseView::createScene()
401 //{
402 // QGLBuilder builder;
403 // QGLSceneNode *root = builder.sceneNode();
404 
405 // //completed building, so finalise
406 // return builder.finalizedSceneNode();
407 //}
408 
409 
410 //*************************************************************************************************************
411 
412 void InverseView::updateActivation(QSharedPointer<Eigen::VectorXd> p_pVecActivation)
413 {
414  VectorXd t_curLabelActivation = VectorXd::Zero(m_pSceneNode->palette()->size());
415 
416  qint32 actCount = 0;
417  for(qint32 h = 0; h < 2; ++h)
418  {
419  for(qint32 i = 0; i < m_sourceSpace[h].cluster_info.numClust(); ++i)
420  {
421  qint32 labelId = m_sourceSpace[h].cluster_info.clusterLabelIds[i];
422  qint32 colorIdx = m_qListMapLabelIdIndex[h][labelId];
423 
424  //search for max activation within one label - by checking if there is already an assigned value
425  if(abs(t_curLabelActivation[colorIdx]) < abs((*p_pVecActivation.data())[actCount]))//m_curSourceEstimate.data(i, currentSample)))
426  t_curLabelActivation[colorIdx] = (*p_pVecActivation.data())[actCount];//m_curSourceEstimate.data(i, currentSample);
427 
428  ++actCount;
429  }
430  }
431 
432  for(qint32 i = 0; i < m_pSceneNode->palette()->size(); ++i)
433  {
434  qint32 iVal = (t_curLabelActivation[i]/m_pInverseViewProducer->getGlobalMax()) * 255;//300;
435 
436  iVal = iVal > 255 ? 255 : iVal < 0 ? 0 : iVal;
437 
438 // int r, g, b;
439  QRgb qRgb;
440 
441  qRgb = ColorMap::valueToHotNegative1((double)iVal/255.0);
442 // qRgb = ColorMap::valueToHotNegative2((double)iVal/255.0);
443 
444 
445 // if(m_iColorMode == 0)
446 // {
447 // r = iVal;
448 // g = iVal;
449 // b = iVal;
451 // qRgb = ColorMap::valueToHotNegative2((double)iVal/255.0);
452 // }
453 // else if(m_iColorMode == 1)
454 // {
455 // r = iVal;
456 // g = iVal;
457 // b = iVal;
459 // qRgb = ColorMap::valueToHotNegative2((double)iVal/255.0);
460 // }
461 
462  m_pSceneNode->palette()->material(i)->setSpecularColor(QColor(qRgb));
463  //QColor(r,g,b,200));
464  }
465 
466  this->update();
467 }
ColorMap class declaration.
void pushSourceEstimate(MNESourceEstimate &p_sourceEstimate)
void keyPressEvent(QKeyEvent *e)
void paintGL(QGLPainter *painter)
Source Space descritpion.
InverseViewProducer class declaration.
InverseView(const MNESourceSpace &p_sourceSpace, QList< Label > &p_qListLabels, QList< RowVector4i > &p_qListRGBAs, qint32 p_iFps=24, bool p_bLoop=true, bool p_bStereo=false, bool p_bSlowMotion=false, QWindow *parent=0)
Definition: inverseview.cpp:85
void initializeGL(QGLPainter *painter)
void mousePressEvent(QMouseEvent *e)
InverseView class declaration.
Label class declaration.
void mouseMoveEvent(QMouseEvent *e)