262 lines
8.2 KiB
C++
262 lines
8.2 KiB
C++
|
/*
|
||
|
* Copyright (C) 2015 Open Source Robotics Foundation
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
#include "gazebo/rendering/UserCamera.hh"
|
||
|
#include "gazebo/rendering/Visual.hh"
|
||
|
|
||
|
#include "gazebo/gui/Actions.hh"
|
||
|
#include "gazebo/gui/GuiIface.hh"
|
||
|
#include "gazebo/gui/GLWidget.hh"
|
||
|
#include "gazebo/gui/MainWindow.hh"
|
||
|
#include "gazebo/gui/ViewAngleWidgetPrivate.hh"
|
||
|
#include "gazebo/gui/ViewAngleWidget.hh"
|
||
|
|
||
|
using namespace gazebo;
|
||
|
using namespace gui;
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
ViewAngleWidget::ViewAngleWidget(QWidget *_parent)
|
||
|
: QWidget(_parent), dataPtr(new ViewAngleWidgetPrivate)
|
||
|
{
|
||
|
// Keep pointer to main window
|
||
|
this->dataPtr->mainWindow = qobject_cast<MainWindow *>(_parent);
|
||
|
|
||
|
// Lateral buttons
|
||
|
this->dataPtr->topButton = new QToolButton(this);
|
||
|
this->dataPtr->bottomButton = new QToolButton(this);
|
||
|
this->dataPtr->frontButton = new QToolButton(this);
|
||
|
this->dataPtr->backButton = new QToolButton(this);
|
||
|
this->dataPtr->leftButton = new QToolButton(this);
|
||
|
this->dataPtr->rightButton = new QToolButton(this);
|
||
|
|
||
|
// Reset / home button
|
||
|
this->dataPtr->resetButton = new QToolButton(this);
|
||
|
|
||
|
// Button size
|
||
|
QSize iconSize(30, 30);
|
||
|
this->dataPtr->topButton->setIconSize(iconSize);
|
||
|
this->dataPtr->bottomButton->setIconSize(iconSize);
|
||
|
this->dataPtr->frontButton->setIconSize(iconSize);
|
||
|
this->dataPtr->backButton->setIconSize(iconSize);
|
||
|
this->dataPtr->leftButton->setIconSize(iconSize);
|
||
|
this->dataPtr->rightButton->setIconSize(iconSize);
|
||
|
this->dataPtr->resetButton->setIconSize(iconSize);
|
||
|
|
||
|
// Dropdown
|
||
|
this->dataPtr->projectionComboBox = new QComboBox(this);
|
||
|
this->dataPtr->projectionComboBox->setMinimumWidth(150);
|
||
|
this->dataPtr->projectionComboBox->addItem("Perspective", 0);
|
||
|
this->dataPtr->projectionComboBox->addItem("Orthographic", 1);
|
||
|
connect(this->dataPtr->projectionComboBox, SIGNAL(currentIndexChanged(int)),
|
||
|
this, SLOT(OnProjection(int)));
|
||
|
|
||
|
// Main layout
|
||
|
this->dataPtr->mainLayout = new QGridLayout();
|
||
|
this->dataPtr->mainLayout->addWidget(this->dataPtr->projectionComboBox,
|
||
|
3, 0, 1, 4);
|
||
|
this->setLayout(this->dataPtr->mainLayout);
|
||
|
|
||
|
// Connect the ortho action
|
||
|
connect(g_cameraOrthoAct, SIGNAL(triggered()), this, SLOT(OnOrtho()));
|
||
|
|
||
|
// connect the perspective action
|
||
|
connect(g_cameraPerspectiveAct, SIGNAL(triggered()), this,
|
||
|
SLOT(OnPerspective()));
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
ViewAngleWidget::~ViewAngleWidget()
|
||
|
{
|
||
|
delete this->dataPtr;
|
||
|
this->dataPtr = NULL;
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
void ViewAngleWidget::Add(const Mode _mode, QAction *_action)
|
||
|
{
|
||
|
if (_mode == TOP)
|
||
|
{
|
||
|
this->dataPtr->topButton->setDefaultAction(_action);
|
||
|
this->dataPtr->mainLayout->addWidget(this->dataPtr->topButton, 0, 1);
|
||
|
connect(_action, SIGNAL(triggered()), this, SLOT(OnTopView()));
|
||
|
}
|
||
|
else if (_mode == BOTTOM)
|
||
|
{
|
||
|
this->dataPtr->bottomButton->setDefaultAction(_action);
|
||
|
this->dataPtr->mainLayout->addWidget(this->dataPtr->bottomButton, 2, 1);
|
||
|
connect(_action, SIGNAL(triggered()), this, SLOT(OnBottomView()));
|
||
|
}
|
||
|
else if (_mode == FRONT)
|
||
|
{
|
||
|
this->dataPtr->frontButton->setDefaultAction(_action);
|
||
|
this->dataPtr->mainLayout->addWidget(this->dataPtr->frontButton, 1, 1);
|
||
|
connect(_action, SIGNAL(triggered()), this, SLOT(OnFrontView()));
|
||
|
}
|
||
|
else if (_mode == BACK)
|
||
|
{
|
||
|
this->dataPtr->backButton->setDefaultAction(_action);
|
||
|
this->dataPtr->mainLayout->addWidget(this->dataPtr->backButton, 1, 3);
|
||
|
connect(_action, SIGNAL(triggered()), this, SLOT(OnBackView()));
|
||
|
}
|
||
|
else if (_mode == LEFT)
|
||
|
{
|
||
|
this->dataPtr->leftButton->setDefaultAction(_action);
|
||
|
this->dataPtr->mainLayout->addWidget(this->dataPtr->leftButton, 1, 0);
|
||
|
connect(_action, SIGNAL(triggered()), this, SLOT(OnLeftView()));
|
||
|
}
|
||
|
else if (_mode == RIGHT)
|
||
|
{
|
||
|
this->dataPtr->rightButton->setDefaultAction(_action);
|
||
|
this->dataPtr->mainLayout->addWidget(this->dataPtr->rightButton, 1, 2);
|
||
|
connect(_action, SIGNAL(triggered()), this, SLOT(OnRightView()));
|
||
|
}
|
||
|
else if (_mode == RESET)
|
||
|
{
|
||
|
this->dataPtr->resetButton->setDefaultAction(_action);
|
||
|
this->dataPtr->mainLayout->addWidget(this->dataPtr->resetButton, 0, 3);
|
||
|
connect(_action, SIGNAL(triggered()), this, SLOT(OnResetView()));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
void ViewAngleWidget::LookDirection(const ignition::math::Vector3d &_dir)
|
||
|
{
|
||
|
rendering::UserCameraPtr cam = gui::get_active_camera();
|
||
|
if (!cam)
|
||
|
return;
|
||
|
|
||
|
GLWidget *glWidget =
|
||
|
this->dataPtr->mainWindow->findChild<GLWidget *>("GLWidget");
|
||
|
if (!glWidget)
|
||
|
{
|
||
|
gzerr << "GLWidget not found, this should never happen. " <<
|
||
|
"Camera pose won't be changed." << std::endl;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Look at world origin unless there are visuals selected
|
||
|
ignition::math::Vector3d lookAt = ignition::math::Vector3d::Zero;
|
||
|
|
||
|
// If there are selected visuals, look at their center
|
||
|
std::vector<rendering::VisualPtr> selectedVisuals =
|
||
|
glWidget->SelectedVisuals();
|
||
|
|
||
|
if (!selectedVisuals.empty())
|
||
|
{
|
||
|
for (auto const &vis : selectedVisuals)
|
||
|
{
|
||
|
ignition::math::Vector3d visPos = vis->GetWorldPose().pos.Ign();
|
||
|
lookAt += visPos;
|
||
|
}
|
||
|
lookAt /= selectedVisuals.size();
|
||
|
}
|
||
|
|
||
|
// Keep current distance to look target
|
||
|
ignition::math::Vector3d camPos = cam->WorldPose().Pos();
|
||
|
double distance = std::fabs((camPos - lookAt).Length());
|
||
|
|
||
|
// Calculate camera position
|
||
|
ignition::math::Vector3d newCamPos = lookAt - _dir * distance;
|
||
|
|
||
|
// Calculate camera orientation
|
||
|
double roll = 0;
|
||
|
double pitch = -std::atan2(_dir.Z(),
|
||
|
std::sqrt(std::pow(_dir.X(), 2) + std::pow(_dir.Y(), 2)));
|
||
|
double yaw = std::atan2(_dir.Y(), _dir.X());
|
||
|
|
||
|
ignition::math::Quaterniond quat =
|
||
|
ignition::math::Quaterniond(roll, pitch, yaw);
|
||
|
|
||
|
// Move camera to that pose in 1s
|
||
|
cam->MoveToPosition(math::Pose(math::Vector3(newCamPos),
|
||
|
math::Quaternion(quat)), 1);
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
void ViewAngleWidget::OnTopView()
|
||
|
{
|
||
|
this->LookDirection(-ignition::math::Vector3d::UnitZ);
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
void ViewAngleWidget::OnBottomView()
|
||
|
{
|
||
|
this->LookDirection(ignition::math::Vector3d::UnitZ);
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
void ViewAngleWidget::OnFrontView()
|
||
|
{
|
||
|
this->LookDirection(-ignition::math::Vector3d::UnitX);
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
void ViewAngleWidget::OnBackView()
|
||
|
{
|
||
|
this->LookDirection(ignition::math::Vector3d::UnitX);
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
void ViewAngleWidget::OnLeftView()
|
||
|
{
|
||
|
this->LookDirection(ignition::math::Vector3d::UnitY);
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
void ViewAngleWidget::OnRightView()
|
||
|
{
|
||
|
this->LookDirection(-ignition::math::Vector3d::UnitY);
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
void ViewAngleWidget::OnResetView()
|
||
|
{
|
||
|
rendering::UserCameraPtr cam = gui::get_active_camera();
|
||
|
|
||
|
if (!cam)
|
||
|
return;
|
||
|
|
||
|
cam->MoveToPosition(cam->DefaultPose(), 1);
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
void ViewAngleWidget::OnPerspective()
|
||
|
{
|
||
|
this->dataPtr->projectionComboBox->blockSignals(true);
|
||
|
this->dataPtr->projectionComboBox->setCurrentIndex(0);
|
||
|
this->dataPtr->projectionComboBox->blockSignals(false);
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
void ViewAngleWidget::OnOrtho()
|
||
|
{
|
||
|
this->dataPtr->projectionComboBox->blockSignals(true);
|
||
|
this->dataPtr->projectionComboBox->setCurrentIndex(1);
|
||
|
this->dataPtr->projectionComboBox->blockSignals(false);
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
void ViewAngleWidget::OnProjection(int _index)
|
||
|
{
|
||
|
if (_index == 0)
|
||
|
g_cameraPerspectiveAct->trigger();
|
||
|
else if (_index == 1)
|
||
|
g_cameraOrthoAct->trigger();
|
||
|
else
|
||
|
gzwarn << "Projection index [" << _index << "] not recognized" << std::endl;
|
||
|
}
|