/* * QStereoCtrl.cpp * $Id: QStereoCtrl.cpp,v 1.5 2003/03/05 13:59:09 jhirche Exp $ * * Copyright (C) 1999, 2000 Markus Janich, Michael Meissner * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * As a special exception to the GPL, the QGLViewer authors (Markus * Janich, Michael Meissner, Richard Guenther, Alexander Buck and Thomas * Woerner) give permission to link this program with Qt (non-)commercial * edition, and distribute the resulting executable, without including * the source code for the Qt (non-)commercial edition in the source * distribution. * */ // Qt /////// #include #include #include #include #include #include #include #include #include #include #include #include // QGLViewer ////////////// #include "QStereoCtrl.h" #include "QGLViewer.h" // System /////////// #include #include QStereoCtrl::QStereoCtrl(QGLViewer *pViewer, const char *name) :QWidget(NULL, name) /************************************************************/ { m_pViewer = pViewer; QObject::connect(this, SIGNAL(sigApply()), m_pViewer, SLOT(sltUpdateView())); m_maxAllowedAngle = 6.0; m_parallaxAngle = 3.0; m_stereoType = 0; m_createDlg = false; if (m_createDlg) initDlg(); setAngle(m_parallaxAngle); setStereoType(m_stereoType); } QStereoCtrl::~QStereoCtrl(void) /************************************************************/ { } void QStereoCtrl::showDlg(void) /************************************************************/ { if (!m_createDlg) initDlg(); show(); } void QStereoCtrl::hideDlg(void) /************************************************************/ { if (m_createDlg) hide(); } void QStereoCtrl::initDlg(void) /************************************************************/ { const char *stereoTypes[] = { "Type1", "Type2", 0 }; setCaption("StereoDlg"); setFont(QFont("times",10)); m_pTypeCombo = new QComboBox(FALSE, this); m_pTypeCombo->insertStrList(stereoTypes, 2); connect(m_pTypeCombo, SIGNAL(activated(int)), SLOT(sltStereoTypeChanged(int))); QVBoxLayout *topLayout = new QVBoxLayout(this, 10); QGridLayout *anglesLayout = new QGridLayout(3,2); topLayout->addWidget(m_pTypeCombo); topLayout->addLayout(anglesLayout); QLabel *angleLabel = new QLabel(this); angleLabel->setText("max. Angle:"); angleLabel->setMinimumSize(angleLabel->sizeHint()); m_pAngleSlider = new QSlider (0, 100, 1, 0, QSlider::Horizontal, this, "m_pAngleSlider"); m_pAngleSlider->setTickInterval(10); m_pAngleSlider->setTickmarks(QSlider::Both); m_pAngleSlider->setMinimumSize(m_pAngleSlider->sizeHint()); m_pAngleSlider->setFocusPolicy(NoFocus); connect(m_pAngleSlider, SIGNAL(sliderMoved(int)), this, SLOT(sltAngleChanged(int))); anglesLayout->addWidget(angleLabel,0,0); anglesLayout->addWidget(m_pAngleSlider,0,1); m_createDlg = true; setAngle(m_parallaxAngle); setStereoType(m_stereoType); topLayout->activate(); } void QStereoCtrl::setValues(int type, float parallaxAngle) /************************************************************/ { setAngle(parallaxAngle); setStereoType(type); } void QStereoCtrl::setAngle(float angle) /************************************************************/ { if (angle > m_maxAllowedAngle) m_parallaxAngle = m_maxAllowedAngle; else m_parallaxAngle = angle; if (m_createDlg) m_pAngleSlider->setValue(int(100.0*m_parallaxAngle/m_maxAllowedAngle)); } void QStereoCtrl::setStereoType(int type) /************************************************************/ { m_stereoType = type; if (m_createDlg) m_pTypeCombo->setCurrentItem(type); } void QStereoCtrl::sltAngleChanged(int value) /************************************************************/ { m_parallaxAngle = float(value)*m_maxAllowedAngle/100.0; sigApply(); } void QStereoCtrl::sltStereoTypeChanged(int type) /************************************************************/ { m_stereoType = type; sigApply(); } void QStereoCtrl::activateLeftStereoFrustum(void) /************************************************************/ { activateStereoFrustum(1); } void QStereoCtrl::activateRightStereoFrustum(void) /************************************************************/ { activateStereoFrustum(-1); } void QStereoCtrl::activateStereoFrustum(int dir) /************************************************************/ { CP4D eyePos = m_pViewer->getCameraPtr()->getEyePos(); CP4D refPoint = m_pViewer->getCameraPtr()->getRefPoint(); CV4D viewDir = m_pViewer->getCameraPtr()->getViewDir(); viewDir[3]=0.0; double ardVVolume[6]; m_pViewer->getCameraPtr()->getVVolume(ardVVolume); CBoundingBox3D bbox = m_pViewer->getCameraPtr()->getBoundingBox(); double rdNear = ardVVolume[4]; double rdFar = ardVVolume[5]; float bboxRadius = 0.5*(rdFar-rdNear); CP3D c=bbox.getCenter(); float distEyePosRefPoint = sqrt((eyePos[0]-refPoint[0])*(eyePos[0]-refPoint[0]) + (eyePos[1]-refPoint[1])*(eyePos[1]-refPoint[1]) + (eyePos[2]-refPoint[2])*(eyePos[2]-refPoint[2])); float distEyePosCenterBBoxOrtho = (c[0]-eyePos[0])*viewDir[0] + (c[1]-eyePos[1])*viewDir[1] + (c[2]-eyePos[2])*viewDir[2]; float tc; float eyeSeparation, frustumShift; switch(m_stereoType) { case 0: tc = tan(m_parallaxAngle*M_PI/360.0)*2.0*distEyePosCenterBBoxOrtho*(distEyePosRefPoint/bboxRadius-1.0); eyeSeparation = tc/2.0; frustumShift = rdNear*eyeSeparation/distEyePosCenterBBoxOrtho; break; case 1: rdNear = distEyePosRefPoint - bboxRadius; rdFar = distEyePosRefPoint + bboxRadius; tc = tan(m_parallaxAngle*M_PI/360.0)*2.0*distEyePosRefPoint*(distEyePosRefPoint/(distEyePosRefPoint-rdNear)-1.0); eyeSeparation = tc/2.0; frustumShift = ardVVolume[4]*eyeSeparation/distEyePosRefPoint; break; default: eyeSeparation = 0.0; frustumShift = 0.0; break; } if (m_pViewer->getCameraPtr()->getCameraType()==CCamera::perspective) ::glFrustum(ardVVolume[0]+dir*frustumShift, ardVVolume[1]+dir*frustumShift, ardVVolume[2], ardVVolume[3], ardVVolume[4], ardVVolume[5]); else ::glOrtho(ardVVolume[0]+dir*frustumShift, ardVVolume[1]+dir*frustumShift, ardVVolume[2], ardVVolume[3], ardVVolume[4], ardVVolume[5]); glTranslatef(dir*eyeSeparation, 0.0, 0.0); }