ATLAS Offline Software
Loading...
Searching...
No Matches
VP1CustomSteroEditor.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3*/
4
5
7// //
8// Implementation of class VP1CustomStereoEditor //
9// //
10// Author: Riccardo-Maria BIANCH (rbianchi@cern.ch) //
11// Initial version: August 2013 //
12// //
14
15#include "ui_vp1customstereoeditor.h"
16
24#include "VP1Base/VP1Msg.h"
25
26#include <Inventor/nodes/SoGroup.h>
27#include <Inventor/nodes/SoCamera.h>
28#include <Inventor/SbBox.h>
29
30#include <QShortcut>
31#include <QCloseEvent>
32#include <QScrollBar>
33
34//____________________________________________________________________
36public:
37
39 Ui::VP1CustomStereoEditorForm ui;
41// QWidget * frameHolderWidget;
42// QList<VP1CustomTourFrameWidget*> frames;
43// QList<QObject*> objectsToDisableWhenTourUnavailable;
44// void updateFrameListVisuals();
45// void updateFrameStepControlsEnablement();
46// void updateFrameSnapshot(VP1CustomTourFrameWidget*);
47// int countEnabledFrames( int& nEnabledPerspectiveFrames,
48// int& nEnabledOrthographicFrames ) const;
49// void addFrame(VP1CustomTourFrameWidget*frame);
50
51};
52
53
54// TODO: implement stereo settings save
56//QByteArray VP1CustomStereoEditor::state() const
57//{
58// VP1Serialise s(0/*version*/);
59// QList<QByteArray> frameStates;
60// for(VP1CustomTourFrameWidget*frame : m_d->frames) {
61// frameStates << frame->serialise();
62// s.ignoreWidget(frame);
63// }
64// s.save(frameStates);
65// s.save(m_d->ui.doubleSpinBox_theta);
66// s.save(m_d->ui.doubleSpinBox_radius);
67// s.save(m_d->ui.groupBox_utilityZoom);
68// s.warnUnsaved(this);
69// return s.result();
70//}
71//
73//void VP1CustomStereoEditor::setState(QByteArray ba)
74//{
75// for(VP1CustomTourFrameWidget*frame : m_d->frames)
76// frame->deleteLater();
77// m_d->frames.clear();
78//
79// VP1Deserialise s(ba);
80// if (s.version()!=0)
81// return;
82// QList<QByteArray> frameStates = s.restore<QList<QByteArray> >();
83// s.restore(m_d->ui.doubleSpinBox_theta);
84// s.restore(m_d->ui.doubleSpinBox_radius);
85// s.restore(m_d->ui.groupBox_utilityZoom);
86// s.warnUnrestored(this);
87//
88// m_d->ui.widget_utilityZoomContents->setVisible(m_d->ui.groupBox_utilityZoom->isChecked());
89//
90// for(QByteArray ba2 : frameStates)
91// m_d->addFrame(new VP1CustomTourFrameWidget(ba2));
92// m_d->updateFrameListVisuals();
93// enabledFrameListChanged();
94//}
95
96
97
98
99
100
101
102//____________________________________________________________________
104: QWidget(0,Qt::WindowStaysOnTopHint), m_d(new Imp)
105{
106 VP1Msg::messageDebug("VP1CustomStereoEditor::VP1CustomStereoEditor()");
107
108 // set the default anaglyph masks
109 m_leftEyeFilter_def[0] = true; m_leftEyeFilter_def[1] = false; m_leftEyeFilter_def[2] = false;
110 m_rightEyeFilter_def[0] = false; m_rightEyeFilter_def[1] = true; m_rightEyeFilter_def[2] = true;
111
112 m_d->theclass = this;
113 m_d->ui.setupUi(this);
114 m_d->ui.groupBox_camera->setChecked(true);
115 m_d->ui.groupBox_viewer->setChecked(false);
116 // m_d->ui.widget_utilityZoomContents->setVisible(false);
117
118 // a handle on the main viewer widget
119 m_d->viewer = viewer;
120
121 setWindowIcon(QIcon(QString(":/vp1/icons/icons/3d_32x32.png")));
122
123 // set default values
124 m_d->ui.label_focal->setText( QString::number(m_d->viewer->getCamera()->focalDistance.getValue()) );
125 m_d->ui.doubleSpinBox_offset->setValue(m_d->viewer->stereo_offset_camera);
126 m_d->ui.doubleSpinBox_parallax->setValue(m_d->viewer->stereo_parallax_camera);
127 m_d->ui.doubleSpinBox_offset_viewer->setValue(m_d->viewer->stereo_offset_viewer);
128
129
130 connect(m_d->ui.pushButton_focal,SIGNAL(clicked()),this,SLOT(updateFocal()));
131
132 connect(m_d->ui.pushButton_setToFocal30,SIGNAL(clicked()),this,SLOT(setToFocal30()));
133
134
135 connect(m_d->ui.pushButton_defCamera,SIGNAL(clicked()),this,SLOT(buttonClicked()));
136 connect(m_d->ui.pushButton_defViewer,SIGNAL(clicked()),this,SLOT(buttonClicked()));
137
138 connect(m_d->ui.pushButton_refresh,SIGNAL(clicked()),this,SLOT(buttonClicked()));
139 connect(m_d->ui.pushButton_refreshViewer,SIGNAL(clicked()),this,SLOT(buttonClicked()));
140
141 connect(m_d->ui.radioButton_standard,SIGNAL(toggled(bool)),this,SLOT(changedView(bool)));
142 connect(m_d->ui.radioButton_left,SIGNAL(toggled(bool)),this,SLOT(changedView(bool)));
143 connect(m_d->ui.radioButton_right,SIGNAL(toggled(bool)),this,SLOT(changedView(bool)));
144
145 connect(m_d->ui.radioButton_left_viewer,SIGNAL(toggled(bool)),this,SLOT(changedView_viewer(bool)));
146 connect(m_d->ui.radioButton_right_viewer,SIGNAL(toggled(bool)),this,SLOT(changedView_viewer(bool)));
147 connect(m_d->ui.radioButton_standard_viewer,SIGNAL(toggled(bool)),this,SLOT(changedView_viewer(bool)));
148
149 connect(m_d->ui.radioButton_noStereo,SIGNAL(toggled(bool)),this,SLOT(changedView_viewer(bool)));
150 connect(m_d->ui.radioButton_anaglyph,SIGNAL(toggled(bool)),this,SLOT(changedView_viewer(bool)));
151 connect(m_d->ui.radioButton_quadbuffer,SIGNAL(toggled(bool)),this,SLOT(changedView_viewer(bool)));
152 connect(m_d->ui.radioButton_int_rows,SIGNAL(toggled(bool)),this,SLOT(changedView_viewer(bool)));
153 connect(m_d->ui.radioButton_int_cols,SIGNAL(toggled(bool)),this,SLOT(changedView_viewer(bool)));
154
155 connect(m_d->ui.doubleSpinBox_imageWidth_meter,SIGNAL(valueChanged(double)),this,SLOT(perform3DCalculations(double)));
156 connect(m_d->ui.doubleSpinBox_imageWidth_inch,SIGNAL(valueChanged(double)),this,SLOT(perform3DCalculations(double)));
157 connect(m_d->ui.doubleSpinBox_offset,SIGNAL(valueChanged(double)),this,SLOT(perform3DCalculations(double)));
158
159
169 m_d->ui.groupBox_viewer->hide();
170
171}
172
173//____________________________________________________________________
175{
176 // m_d->frameHolderWidget->deleteLater();
177 // for(VP1CustomTourFrameWidget*frame : m_d->frames)
178 // frame->deleteLater();
179 delete m_d;
180}
181
182
183//____________________________________________________________________
184/*
185 * Overriding the QWidget event to
186 * update the spinbox with the default or current values every time
187 * the editor widget is shown.
188 */
190{
191 // set default values
192
193 m_d->ui.label_focal->setText( QString::number(m_d->viewer->getCamera()->focalDistance.getValue()) );
194
195 m_d->ui.doubleSpinBox_offset->setValue(m_d->viewer->stereo_offset_camera);
196 m_d->ui.doubleSpinBox_parallax->setValue(m_d->viewer->stereo_parallax_camera);
197 m_d->ui.doubleSpinBox_offset_viewer->setValue(m_d->viewer->stereo_offset_viewer);
198
199 m_d->ui.radioButton_standard->setChecked(true);
200 m_d->ui.radioButton_noStereo->setChecked(true);
201 m_d->ui.radioButton_standard_viewer->setChecked(true);
202
203 m_d->ui.groupBox_2->setEnabled(false);
204
205 // go on with the default QWidget behavior
206 QWidget::showEvent(ev);
207}
208
209
210//____________________________________________________________________
212{
213 ev->ignore();
214 hide();
215}
216
217
218
219//____________________________________________________________________
221{
222 m_d->ui.label_focal->setText( QString::number(m_d->viewer->getCamera()->focalDistance.getValue()) );
223}
224
225
226//____________________________________________________________________
228{
229 m_d->ui.doubleSpinBox_offset->setValue( (m_d->viewer->getCamera()->focalDistance.getValue() / 30.0) );
230 m_d->ui.doubleSpinBox_offset_viewer->setValue( (m_d->viewer->getCamera()->focalDistance.getValue() / 30.0) );
231}
232
233
234//____________________________________________________________________
236{
237 double value_meters = 0.;
238
239 if (m_d->ui.doubleSpinBox_imageWidth_meter==sender()) {
240 // converting meters to inches, and set the new value on the screen
241 m_d->ui.doubleSpinBox_imageWidth_inch->setValue( value * 39.370);
242 value_meters = value;
243 }
244 else if (m_d->ui.doubleSpinBox_imageWidth_inch==sender()) {
245 // converting inches to meters, and set the new value on the screen
246 m_d->ui.doubleSpinBox_imageWidth_meter->setValue( value / 39.370);
247 value_meters = value / 39.370;
248 }
249 else {
250 value_meters = m_d->ui.doubleSpinBox_imageWidth_meter->value();
251 }
252
253 // perform S3D calculations
254 // --> see: http://www.dashwood3d.com/blog/beginners-guide-to-shooting-stereoscopic-3d/
255 double nativeParallax = m_d->ui.doubleSpinBox_offset->value() / value_meters;
256 double minimumObjDistance = m_d->ui.doubleSpinBox_offset->value() / 30.;
257
258 // update the S3D values
259 m_d->ui.label_nativeParalValue->setText( QString::number(nativeParallax) );
260 m_d->ui.label_minObjDistValue->setText( QString::number(minimumObjDistance) );
261
262}
263
264
265
266//____________________________________________________________________
268{
269 if (checked) {
270 SoCamera *camera = m_d->viewer->getCamera();
271 if (m_d->ui.radioButton_standard->isChecked() ) {
272 camera->setStereoMode(SoCamera::MONOSCOPIC);
273 VP1Msg::messageDebug("Changed camera STEREO view to STANDARD.");
274 }
275 else if (m_d->ui.radioButton_left->isChecked() ) {
276 camera->setStereoMode(SoCamera::LEFT_VIEW);
277 VP1Msg::messageDebug("Changed camera STEREO view to LEFT EYE.");
278 }
279 else if (m_d->ui.radioButton_right->isChecked() ) {
280 camera->setStereoMode(SoCamera::RIGHT_VIEW);
281 VP1Msg::messageDebug("Changed camera STEREO view to RIGHT EYE.");
282 }
283 m_d->viewer->show(); // update the view
284 }
285}
286
288{
289 if (checked) {
290 // we only show the LEFT view in REAL color
291 if (m_d->ui.radioButton_left_viewer->isChecked())
292 {
293 m_leftEyeFilter[0] = true; m_leftEyeFilter[1] = true; m_leftEyeFilter[2] = true;
294 m_rightEyeFilter[0] = false; m_rightEyeFilter[1] = false; m_rightEyeFilter[2] = false;
295 m_d->viewer->setAnaglyphStereoColorMasksSlot(m_leftEyeFilter, m_rightEyeFilter);
296 }
297 // we only show the RIGHT view in REAL color
298 if (m_d->ui.radioButton_right_viewer->isChecked())
299 {
300 m_leftEyeFilter[0] = false; m_leftEyeFilter[1] = false; m_leftEyeFilter[2] = false;
301 m_rightEyeFilter[0] = true; m_rightEyeFilter[1] = true; m_rightEyeFilter[2] = true;
302 m_d->viewer->setAnaglyphStereoColorMasksSlot(m_leftEyeFilter, m_rightEyeFilter);
303 }
304 // we set the standard Red/Cyan anaglyph view
305 if (m_d->ui.radioButton_standard_viewer->isChecked())
306 {
307 m_d->viewer->setAnaglyphStereoColorMasksSlot(m_leftEyeFilter_def, m_rightEyeFilter_def);
308 }
309 if (m_d->ui.radioButton_noStereo->isChecked())
310 {
311 m_d->viewer->setStereoTypeSlot(SoQtViewer::STEREO_NONE);
312 m_d->ui.groupBox_2->setEnabled(false);
313 }
314 if (m_d->ui.radioButton_anaglyph->isChecked())
315 {
316 m_d->viewer->setStereoTypeSlot(SoQtViewer::STEREO_ANAGLYPH);
317 m_d->ui.groupBox_2->setEnabled(true);
318 }
319 if (m_d->ui.radioButton_quadbuffer->isChecked())
320 {
321 m_d->viewer->setStereoTypeSlot(SoQtViewer::STEREO_QUADBUFFER);
322 m_d->ui.groupBox_2->setEnabled(true);
323 }
324 if (m_d->ui.radioButton_int_rows->isChecked())
325 {
326 m_d->viewer->setStereoTypeSlot(SoQtViewer::STEREO_INTERLEAVED_ROWS);
327 m_d->ui.groupBox_2->setEnabled(true);
328 }
329 if (m_d->ui.radioButton_int_cols->isChecked())
330 {
331 m_d->viewer->setStereoTypeSlot(SoQtViewer::STEREO_INTERLEAVED_COLUMNS);
332 m_d->ui.groupBox_2->setEnabled(true);
333 }
334
335
336 m_d->viewer->show(); // update the view
337 }
338}
339
340
341
342//____________________________________________________________________
344{
345 VP1Msg::messageDebug("VP1CustomStereoEditor::buttonClicked() - updating STEREO settings...");
346
348 if (m_d->ui.pushButton_refresh==sender())
349 {
350 // get user's values
351 double offset(m_d->ui.doubleSpinBox_offset->value());
352 double parallax(m_d->ui.doubleSpinBox_parallax->value());
353 // get current values
354 float old_offset = m_d->viewer->stereo_offset_camera;
355 float old_parallax = m_d->viewer->stereo_parallax_camera;
356
357 SoCamera *camera = m_d->viewer->getCamera();
358
359 if (old_offset != offset) {
360 camera->setStereoAdjustment(offset);
361 m_d->viewer->stereo_offset_camera = offset;
362 VP1Msg::messageDebug("Changed CAMERA STEREO offset to: "+QString::number(offset));
363 }
364 if (old_parallax != parallax) {
365 camera->setBalanceAdjustment(parallax);
366 m_d->viewer->stereo_parallax_camera = parallax;
367 VP1Msg::messageDebug("Changed CAMERA STEREO balance/parallax to : "+QString::number(parallax));
368 }
369
370 }
371
372
374 else if (m_d->ui.pushButton_refreshViewer==sender())
375 {
376 // get user's value
377 double offset(m_d->ui.doubleSpinBox_offset_viewer->value());
378 // get current value
379 float old_offset = m_d->viewer->stereo_offset_viewer;
380
381 if (old_offset != offset) {
382 m_d->viewer->setStereoOffsetSlot(offset);
383 m_d->viewer->stereo_offset_viewer = offset;
384 VP1Msg::messageDebug("Changed VIEWER STEREO offset to: "+QString::number(offset));
385 }
386 }
387
389 else if (m_d->ui.pushButton_defCamera==sender())
390 {
391 // set default values
392
393 /*
394 * Default Interaxial (aka Stereo Base) distance.
395 *
396 * The value is chosen because it's the approximate distance between the human eyes.
397 * See:
398 * - http://doc.coin3d.org/Coin/classSoCamera.html#a6ed2d2527604e86cc8be234b1e429991
399 * - http://www.sky.com/shop/export/sites/www.sky.com/shop/__PDF/3D/Basic_Principles_of_Stereoscopic_3D_v1.pdf
400 * - http://www.dashwood3d.com/blog/beginners-guide-to-shooting-stereoscopic-3d/
401 */
402 double defOff = 0.1;
403
404 /*
405 * Default Zero Parallax Plane
406 *
407 * The value 1.0 for the Balance/Parallax, puts the Zero Parallax Plane at the Focal Legth.
408 *
409 * See:
410 * - http://www.dashwood3d.com/blog/beginners-guide-to-shooting-stereoscopic-3d/
411 * - http://www.cafedownloads.com/reviews/r13/3dstereo.html
412 */
413 double defParall = 1.0;
414
415 m_d->ui.doubleSpinBox_offset->setValue(defOff);
416 m_d->ui.doubleSpinBox_parallax->setValue(defParall);
417
418 }
419
420
422 else if (m_d->ui.pushButton_defViewer==sender())
423 {
424 // set default values
425
426 /* Default Interaxial (aka Stereo Base) distance.
427 * The value is chosen because it's the approximate distance between the human eyes.
428 * See:
429 * - http://doc.coin3d.org/Coin/classSoCamera.html#a6ed2d2527604e86cc8be234b1e429991
430 * - http://www.sky.com/shop/export/sites/www.sky.com/shop/__PDF/3D/Basic_Principles_of_Stereoscopic_3D_v1.pdf
431 * - http://www.dashwood3d.com/blog/beginners-guide-to-shooting-stereoscopic-3d/
432 */
433 double defOff = 0.1;
434
435 m_d->ui.doubleSpinBox_offset_viewer->setValue(defOff);
436
437 }
438
439
440}
441
442
443
444//
446//void VP1CustomStereoEditor::Imp::updateFrameSnapshot(VP1CustomTourFrameWidget* frame)
447//{
448// QPixmap pm = viewer->getSnapShotFromCamState(frame->camStateIsPerspective(),frame->camState(),
449// frame->snapShotWidth(),frame->snapShotHeight());
450// if (!pm.isNull())
451// frame->setSnapshot(pm);
452//}
453//
455//int VP1CustomStereoEditor::Imp::countEnabledFrames( int& nEnabledPerspectiveFrames,
456// int& nEnabledOrthographicFrames ) const
457//{
458// nEnabledPerspectiveFrames = 0;
459// nEnabledOrthographicFrames = 0;
460// for(VP1CustomTourFrameWidget*frame : frames) {
461// if (frame->frameIsEnabled()) {
462// if (frame->camStateIsPerspective())
463// ++nEnabledPerspectiveFrames;
464// else
465// ++nEnabledOrthographicFrames;
466// }
467// }
468// return nEnabledPerspectiveFrames+nEnabledOrthographicFrames;
469//}
470//
471//
473//void VP1CustomStereoEditor::enabledFrameListChanged()
474//{
475// int nEnabledPerspectiveFrames, nEnabledOrthographicFrames;
476// int n = m_d->countEnabledFrames( nEnabledPerspectiveFrames,
477// nEnabledOrthographicFrames );
478// QString s("dummy");
479// bool enable(true);
480// if (n<2) {
481// s = "Add at least two frames for tour";
482// enable=false;
483// } else {
484// if (nEnabledPerspectiveFrames>0&&nEnabledOrthographicFrames>0) {
485// s = "Mixed camera types are forbidden";
486// enable=false;
487// } else {
488// if (nEnabledPerspectiveFrames>0)
489// s="Perspective camera tour";
490// else
491// s="Orthographic camera tour";
492// }
493// }
494// m_d->ui.label_statustext->setText(s);
495//
496// for (QObject * o : m_d->objectsToDisableWhenTourUnavailable) {
497// if (o->isWidgetType())
498// static_cast<QWidget*>(o)->setEnabled(enable);
499// else
500// static_cast<QAction*>(o)->setEnabled(enable);
501// }
502//}
503//
505//bool VP1CustomStereoEditor::tourAvailable() const
506//{
507// int nEnabledPerspectiveFrames, nEnabledOrthographicFrames;
508// int n = m_d->countEnabledFrames( nEnabledPerspectiveFrames,
509// nEnabledOrthographicFrames );
510// if (nEnabledPerspectiveFrames>0&&nEnabledOrthographicFrames>0)
511// return false;
512// return n>=2;
513//}
514//
516//bool VP1CustomStereoEditor::tourIsPerspective() const
517//{
518// int nEnabledPerspectiveFrames, nEnabledOrthographicFrames;
519// m_d->countEnabledFrames( nEnabledPerspectiveFrames,
520// nEnabledOrthographicFrames );
521//
522// return nEnabledOrthographicFrames==0;
523//}
524//
526//void VP1CustomStereoEditor::addTourToAnimationSequencer(AnimationSequencer&as,bool jumpDirectlyToFirstFrame) const
527//{
528// if (!tourAvailable())
529// return;
530// bool firstInDirectJump(jumpDirectlyToFirstFrame);
531// for(VP1CustomTourFrameWidget*frame : m_d->frames) {
532// if (frame->frameIsEnabled()) {
533// double t(frame->zoomToFrameTime());
534// if (firstInDirectJump) {
535// t = 0.0;
536// firstInDirectJump = false;
537// }
538// as.sequence().addFrame(frame->camState(),t,
539// frame->zoomToFrameWithVariableSpeed(),
540// frame->zoomToFrameForcedCircular() );
541// if (frame->stayOnFrameTime()>0.0)
542// as.sequence().addFrame(frame->camState(),frame->stayOnFrameTime(),false);
543// }
544// }
545//}
546//
548//void VP1CustomStereoEditor::disableObjectWhenTourNotAvailable(QObject *o)
549//{
550// if (o)
551// m_d->objectsToDisableWhenTourUnavailable << o;
552//}
Ui::VP1CustomStereoEditorForm ui
VP1CustomStereoEditor * theclass
void showEvent(QShowEvent *ev)
void perform3DCalculations(double value)
void changedView_viewer(bool checked)
VP1CustomStereoEditor(VP1ExaminerViewer *)
void closeEvent(QCloseEvent *)
static void messageDebug(const QString &)
Definition VP1Msg.cxx:39
int ev
Definition globals.cxx:25