600 lines
18 KiB
C++
600 lines
18 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/common/MeshManager.hh"
|
|
|
|
#include "gazebo/rendering/Material.hh"
|
|
#include "gazebo/rendering/MovableText.hh"
|
|
#include "gazebo/rendering/DynamicLines.hh"
|
|
#include "gazebo/rendering/Scene.hh"
|
|
#include "gazebo/rendering/Visual.hh"
|
|
#include "gazebo/rendering/SelectionObj.hh"
|
|
#include "gazebo/rendering/ApplyWrenchVisualPrivate.hh"
|
|
#include "gazebo/rendering/ApplyWrenchVisual.hh"
|
|
|
|
using namespace gazebo;
|
|
using namespace rendering;
|
|
|
|
/////////////////////////////////////////////////
|
|
ApplyWrenchVisual::ApplyWrenchVisual(const std::string &_name,
|
|
VisualPtr _parentVis)
|
|
: Visual(*new ApplyWrenchVisualPrivate, _name, _parentVis, false)
|
|
{
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
ApplyWrenchVisual::~ApplyWrenchVisual()
|
|
{
|
|
this->Fini();
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
void ApplyWrenchVisual::Fini()
|
|
{
|
|
ApplyWrenchVisualPrivate *dPtr =
|
|
reinterpret_cast<ApplyWrenchVisualPrivate *>(this->dataPtr);
|
|
|
|
if (dPtr->torqueVisual && dPtr->torqueLine)
|
|
dPtr->torqueVisual->DeleteDynamicLine(dPtr->torqueLine);
|
|
|
|
if (!dPtr->scene)
|
|
return;
|
|
|
|
// Destroy objects and nodes
|
|
Ogre::SceneManager *manager = dPtr->scene->OgreSceneManager();
|
|
if (!manager)
|
|
return;
|
|
|
|
std::vector<std::string> suffixes = {
|
|
"_FORCE_SHAFT_",
|
|
"_FORCE_HEAD_",
|
|
"_FORCE_TEXT_",
|
|
"_TORQUE_TUBE_",
|
|
"_TORQUE_HEAD_",
|
|
"_TORQUE_TEXT_"};
|
|
|
|
for (auto suffix : suffixes)
|
|
{
|
|
std::string name = this->GetName() + suffix;
|
|
if (manager->hasEntity(name))
|
|
manager->destroyMovableObject(manager->getEntity(name));
|
|
|
|
name += "NODE_";
|
|
if (manager->hasSceneNode(name))
|
|
manager->destroySceneNode(manager->getSceneNode(name));
|
|
}
|
|
|
|
// Remove visuals
|
|
if (dPtr->forceVisual &&
|
|
dPtr->scene->GetVisual(dPtr->forceVisual->GetName()))
|
|
{
|
|
dPtr->scene->RemoveVisual(dPtr->forceVisual);
|
|
}
|
|
|
|
if (dPtr->torqueVisual &&
|
|
dPtr->scene->GetVisual(dPtr->torqueVisual->GetName()))
|
|
{
|
|
dPtr->scene->RemoveVisual(dPtr->torqueVisual);
|
|
}
|
|
|
|
if (dPtr->rotTool &&
|
|
dPtr->scene->GetVisual(dPtr->rotTool->GetName()))
|
|
{
|
|
dPtr->rotTool->Fini();
|
|
dPtr->scene->RemoveVisual(dPtr->rotTool);
|
|
}
|
|
|
|
dPtr->forceVisual.reset();
|
|
dPtr->torqueVisual.reset();
|
|
dPtr->rotTool.reset();
|
|
|
|
Visual::Fini();
|
|
}
|
|
|
|
///////////////////////////////////////////////////
|
|
void ApplyWrenchVisual::Load()
|
|
{
|
|
Visual::Load();
|
|
|
|
ApplyWrenchVisualPrivate *dPtr =
|
|
reinterpret_cast<ApplyWrenchVisualPrivate *>(this->dataPtr);
|
|
|
|
if (!dPtr->scene)
|
|
{
|
|
gzerr << "Visual has no scene, not loading." << std::endl;
|
|
return;
|
|
}
|
|
|
|
dPtr->selectedMaterial = "Gazebo/OrangeTransparentOverlay";
|
|
dPtr->unselectedMaterial = "Gazebo/DarkOrangeTransparentOverlay";
|
|
|
|
// Force visual
|
|
dPtr->forceVisual.reset(new rendering::Visual(
|
|
this->GetName() + "_FORCE_VISUAL_", shared_from_this()));
|
|
dPtr->forceVisual->Load();
|
|
|
|
// Force shaft
|
|
this->InsertMesh("axis_shaft");
|
|
|
|
Ogre::MovableObject *shaftObj =
|
|
(Ogre::MovableObject*)(dPtr->scene->OgreSceneManager()->createEntity(
|
|
this->GetName()+"_FORCE_SHAFT_", "axis_shaft"));
|
|
shaftObj->setRenderQueueGroup(Ogre::RENDER_QUEUE_OVERLAY);
|
|
shaftObj->getUserObjectBindings().setUserAny(
|
|
Ogre::Any(std::string(dPtr->forceVisual->GetName())));
|
|
|
|
Ogre::SceneNode *shaftNode =
|
|
dPtr->forceVisual->GetSceneNode()->createChildSceneNode(
|
|
this->GetName() + "_FORCE_SHAFT_NODE_");
|
|
shaftNode->attachObject(shaftObj);
|
|
shaftNode->setPosition(0, 0, 0.1);
|
|
|
|
// Force head
|
|
this->InsertMesh("axis_head");
|
|
|
|
Ogre::MovableObject *headObj =
|
|
(Ogre::MovableObject*)(dPtr->scene->OgreSceneManager()->createEntity(
|
|
this->GetName()+"_FORCE_HEAD_", "axis_head"));
|
|
headObj->setRenderQueueGroup(Ogre::RENDER_QUEUE_OVERLAY);
|
|
headObj->getUserObjectBindings().setUserAny(
|
|
Ogre::Any(std::string(dPtr->forceVisual->GetName())));
|
|
|
|
Ogre::SceneNode *headNode =
|
|
dPtr->forceVisual->GetSceneNode()->createChildSceneNode(
|
|
this->GetName() + "_FORCE_HEAD_NODE_");
|
|
headNode->attachObject(headObj);
|
|
headNode->setPosition(0, 0, 0.24);
|
|
|
|
dPtr->forceVisual->SetMaterial(dPtr->unselectedMaterial);
|
|
dPtr->forceVisual->GetSceneNode()->setInheritScale(false);
|
|
|
|
// Force text
|
|
common::Color matAmbient, matDiffuse, matSpecular, matEmissive;
|
|
rendering::Material::GetMaterialAsColor(dPtr->unselectedMaterial,
|
|
matAmbient, matDiffuse, matSpecular, matEmissive);
|
|
dPtr->forceText.Load(this->GetName()+"__FORCE_TEXT__",
|
|
"0N", "Arial", 0.03, matAmbient);
|
|
dPtr->forceText.SetShowOnTop(true);
|
|
|
|
dPtr->forceText.MovableObject::getUserObjectBindings().setUserAny(
|
|
Ogre::Any(std::string(dPtr->forceVisual->GetName())));
|
|
|
|
Ogre::SceneNode *forceTextNode =
|
|
dPtr->forceVisual->GetSceneNode()->createChildSceneNode(
|
|
this->GetName() + "__FORCE_TEXT_NODE__");
|
|
forceTextNode->attachObject(&(dPtr->forceText));
|
|
forceTextNode->setInheritScale(false);
|
|
|
|
// Torque visual
|
|
dPtr->torqueVisual.reset(new rendering::Visual(
|
|
this->GetName() + "_TORQUE_VISUAL_", shared_from_this()));
|
|
dPtr->torqueVisual->Load();
|
|
|
|
// Torque tube
|
|
common::MeshManager::Instance()->CreateTube("torque_tube",
|
|
0.1, 0.15, 0.05, 2, 32, 1.5*M_PI);
|
|
this->InsertMesh("torque_tube");
|
|
|
|
Ogre::MovableObject *tubeObj =
|
|
(Ogre::MovableObject*)(dPtr->scene->OgreSceneManager()->createEntity(
|
|
this->GetName()+"_TORQUE_TUBE_", "torque_tube"));
|
|
tubeObj->setRenderQueueGroup(Ogre::RENDER_QUEUE_OVERLAY);
|
|
tubeObj->getUserObjectBindings().setUserAny(
|
|
Ogre::Any(std::string(dPtr->torqueVisual->GetName())));
|
|
|
|
Ogre::SceneNode *tubeNode =
|
|
dPtr->torqueVisual->GetSceneNode()->createChildSceneNode(
|
|
this->GetName() + "_TORQUE_TUBE_NODE_");
|
|
tubeNode->attachObject(tubeObj);
|
|
|
|
// Torque arrow
|
|
this->InsertMesh("axis_head");
|
|
|
|
Ogre::MovableObject *torqueHeadObj =
|
|
(Ogre::MovableObject*)(dPtr->scene->OgreSceneManager()->createEntity(
|
|
this->GetName()+"_TORQUE_HEAD_", "axis_head"));
|
|
torqueHeadObj->setRenderQueueGroup(Ogre::RENDER_QUEUE_OVERLAY);
|
|
torqueHeadObj->getUserObjectBindings().setUserAny(
|
|
Ogre::Any(std::string(dPtr->torqueVisual->GetName())));
|
|
|
|
Ogre::SceneNode *torqueHeadNode =
|
|
dPtr->torqueVisual->GetSceneNode()->createChildSceneNode(
|
|
this->GetName() + "_TORQUE_HEAD_NODE_");
|
|
torqueHeadNode->attachObject(torqueHeadObj);
|
|
torqueHeadNode->setScale(3, 3, 1);
|
|
torqueHeadNode->setPosition(-0.04, 0.125, 0);
|
|
ignition::math::Quaterniond quat(0, -M_PI/2.0, 0);
|
|
torqueHeadNode->setOrientation(
|
|
Ogre::Quaternion(quat.W(), quat.X(), quat.Y(), quat.Z()));
|
|
|
|
dPtr->torqueVisual->SetMaterial(dPtr->unselectedMaterial);
|
|
dPtr->torqueVisual->GetSceneNode()->setInheritScale(false);
|
|
|
|
// Torque line
|
|
dPtr->torqueLine = dPtr->torqueVisual->
|
|
CreateDynamicLine(rendering::RENDERING_LINE_LIST);
|
|
dPtr->torqueLine->setMaterial(dPtr->unselectedMaterial);
|
|
dPtr->torqueLine->AddPoint(0, 0, 0);
|
|
dPtr->torqueLine->AddPoint(0, 0, 0.1);
|
|
|
|
// Torque text
|
|
dPtr->torqueText.Load(this->GetName()+"__TORQUE_TEXT__",
|
|
"0Nm", "Arial", 0.03, matAmbient);
|
|
dPtr->torqueText.SetShowOnTop(true);
|
|
|
|
dPtr->torqueText.MovableObject::getUserObjectBindings().setUserAny(
|
|
Ogre::Any(std::string(dPtr->torqueVisual->GetName())));
|
|
|
|
Ogre::SceneNode *torqueTextNode =
|
|
dPtr->torqueVisual->GetSceneNode()->createChildSceneNode(
|
|
this->GetName() + "__TORQUE_TEXT_NODE__");
|
|
torqueTextNode->attachObject(&(dPtr->torqueText));
|
|
torqueTextNode->setInheritScale(false);
|
|
|
|
// Rotation manipulator
|
|
dPtr->rotTool.reset(new rendering::SelectionObj(
|
|
this->GetName() + "__SELECTION_OBJ", shared_from_this()));
|
|
dPtr->rotTool->Load();
|
|
dPtr->rotTool->SetMode("rotate");
|
|
dPtr->rotTool->SetHandleVisible(SelectionObj::ROT_X, false);
|
|
dPtr->rotTool->SetHandleMaterial(SelectionObj::ROT_Y,
|
|
"Gazebo/DarkMagentaTransparent");
|
|
dPtr->rotTool->SetHandleMaterial(SelectionObj::ROT_Z,
|
|
"Gazebo/DarkMagentaTransparent");
|
|
|
|
// Initialize
|
|
dPtr->forceVector = ignition::math::Vector3d::Zero;
|
|
dPtr->torqueVector = ignition::math::Vector3d::Zero;
|
|
|
|
this->SetVisibilityFlags(GZ_VISIBILITY_GUI | GZ_VISIBILITY_SELECTABLE);
|
|
this->Resize();
|
|
this->UpdateForceVisual();
|
|
this->UpdateTorqueVisual();
|
|
this->SetMode(Mode::NONE);
|
|
}
|
|
|
|
///////////////////////////////////////////////////
|
|
ignition::math::Quaterniond ApplyWrenchVisual::QuaternionFromVector(
|
|
const ignition::math::Vector3d &_vec)
|
|
{
|
|
double roll = 0;
|
|
double pitch = -atan2(_vec.Z(), sqrt(pow(_vec.X(), 2) + pow(_vec.Y(), 2)));
|
|
double yaw = atan2(_vec.Y(), _vec.X());
|
|
|
|
return ignition::math::Quaterniond(roll, pitch, yaw);
|
|
}
|
|
|
|
///////////////////////////////////////////////////
|
|
void ApplyWrenchVisual::SetCoM(const math::Vector3 &_comVector)
|
|
{
|
|
this->SetCoM(_comVector.Ign());
|
|
}
|
|
|
|
///////////////////////////////////////////////////
|
|
void ApplyWrenchVisual::SetCoM(const ignition::math::Vector3d &_comVector)
|
|
{
|
|
ApplyWrenchVisualPrivate *dPtr =
|
|
reinterpret_cast<ApplyWrenchVisualPrivate *>(this->dataPtr);
|
|
|
|
dPtr->comVector = _comVector;
|
|
|
|
{
|
|
// UpdateTorqueVisual changes torqueVisual
|
|
std::lock_guard<std::mutex> lock(dPtr->mutex);
|
|
|
|
this->UpdateTorqueVisual();
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////
|
|
void ApplyWrenchVisual::SetForcePos(const math::Vector3 &_forcePosVector)
|
|
{
|
|
this->SetForcePos(_forcePosVector.Ign());
|
|
}
|
|
|
|
///////////////////////////////////////////////////
|
|
void ApplyWrenchVisual::SetForcePos(
|
|
const ignition::math::Vector3d &_forcePosVector)
|
|
{
|
|
ApplyWrenchVisualPrivate *dPtr =
|
|
reinterpret_cast<ApplyWrenchVisualPrivate *>(this->dataPtr);
|
|
|
|
dPtr->forcePosVector = _forcePosVector;
|
|
|
|
{
|
|
// UpdateForceVisual changes forceVisual
|
|
std::lock_guard<std::mutex> lock(dPtr->mutex);
|
|
|
|
this->UpdateForceVisual();
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////
|
|
void ApplyWrenchVisual::SetForce(const math::Vector3 &_forceVector,
|
|
const bool _rotatedByMouse)
|
|
{
|
|
this->SetForce(_forceVector.Ign(), _rotatedByMouse);
|
|
}
|
|
|
|
///////////////////////////////////////////////////
|
|
void ApplyWrenchVisual::SetForce(const ignition::math::Vector3d &_forceVector,
|
|
const bool _rotatedByMouse)
|
|
{
|
|
ApplyWrenchVisualPrivate *dPtr =
|
|
reinterpret_cast<ApplyWrenchVisualPrivate *>(this->dataPtr);
|
|
|
|
std::ostringstream mag;
|
|
mag << std::fixed << std::setprecision(3) << _forceVector.Length();
|
|
dPtr->forceText.SetText(mag.str() + "N");
|
|
|
|
dPtr->forceVector = _forceVector;
|
|
dPtr->rotatedByMouse = _rotatedByMouse;
|
|
|
|
if (_forceVector == ignition::math::Vector3d::Zero)
|
|
{
|
|
if (dPtr->torqueVector == ignition::math::Vector3d::Zero)
|
|
this->SetMode(Mode::NONE);
|
|
else
|
|
this->SetMode(Mode::TORQUE);
|
|
}
|
|
else
|
|
{
|
|
this->SetMode(Mode::FORCE);
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////
|
|
void ApplyWrenchVisual::SetTorque(const math::Vector3 &_torqueVector,
|
|
const bool _rotatedByMouse)
|
|
{
|
|
this->SetTorque(_torqueVector.Ign(), _rotatedByMouse);
|
|
}
|
|
|
|
///////////////////////////////////////////////////
|
|
void ApplyWrenchVisual::SetTorque(const ignition::math::Vector3d &_torqueVector,
|
|
const bool _rotatedByMouse)
|
|
{
|
|
ApplyWrenchVisualPrivate *dPtr =
|
|
reinterpret_cast<ApplyWrenchVisualPrivate *>(this->dataPtr);
|
|
|
|
std::ostringstream mag;
|
|
mag << std::fixed << std::setprecision(3) << _torqueVector.Length();
|
|
dPtr->torqueText.SetText(mag.str() + "Nm");
|
|
|
|
dPtr->torqueVector = _torqueVector;
|
|
dPtr->rotatedByMouse = _rotatedByMouse;
|
|
|
|
if (_torqueVector == ignition::math::Vector3d::Zero)
|
|
{
|
|
if (dPtr->forceVector == ignition::math::Vector3d::Zero)
|
|
this->SetMode(Mode::NONE);
|
|
else
|
|
this->SetMode(Mode::FORCE);
|
|
}
|
|
else
|
|
{
|
|
this->SetMode(Mode::TORQUE);
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////
|
|
void ApplyWrenchVisual::UpdateForceVisual()
|
|
{
|
|
ApplyWrenchVisualPrivate *dPtr =
|
|
reinterpret_cast<ApplyWrenchVisualPrivate *>(this->dataPtr);
|
|
|
|
if (!dPtr->forceVisual || !dPtr->rotTool)
|
|
{
|
|
gzwarn << "No force visual" << std::endl;
|
|
return;
|
|
}
|
|
|
|
ignition::math::Vector3d normVec = dPtr->forceVector;
|
|
normVec.Normalize();
|
|
|
|
// Place it on X axis in case it is zero
|
|
if (normVec == ignition::math::Vector3d::Zero)
|
|
normVec = ignition::math::Vector3d::UnitX;
|
|
|
|
// Set rotation in the vector direction
|
|
ignition::math::Quaterniond quat = this->QuaternionFromVector(normVec);
|
|
dPtr->forceVisual->SetRotation(quat * ignition::math::Quaterniond(
|
|
ignition::math::Vector3d(0, M_PI/2.0, 0)));
|
|
|
|
// Set arrow tip to forcePosVector
|
|
dPtr->forceVisual->SetPosition(-normVec * 0.28 *
|
|
dPtr->forceVisual->GetScale().z + dPtr->forcePosVector);
|
|
|
|
// Rotation tool
|
|
dPtr->rotTool->SetPosition(dPtr->forcePosVector);
|
|
if (!dPtr->rotatedByMouse)
|
|
dPtr->rotTool->SetRotation(quat);
|
|
}
|
|
|
|
///////////////////////////////////////////////////
|
|
void ApplyWrenchVisual::UpdateTorqueVisual()
|
|
{
|
|
ApplyWrenchVisualPrivate *dPtr =
|
|
reinterpret_cast<ApplyWrenchVisualPrivate *>(this->dataPtr);
|
|
|
|
if (!dPtr->torqueVisual || !dPtr->rotTool)
|
|
{
|
|
gzwarn << "No torque visual" << std::endl;
|
|
return;
|
|
}
|
|
|
|
ignition::math::Vector3d normVec = dPtr->torqueVector;
|
|
normVec.Normalize();
|
|
|
|
// Place it on X axis in case it is zero
|
|
if (normVec == ignition::math::Vector3d::Zero)
|
|
normVec = ignition::math::Vector3d::UnitX;
|
|
|
|
// Set rotation in the vector direction
|
|
ignition::math::Quaterniond quat = this->QuaternionFromVector(normVec);
|
|
dPtr->torqueVisual->SetRotation(quat * ignition::math::Quaterniond(
|
|
ignition::math::Vector3d(0, M_PI/2.0, 0)));
|
|
|
|
// Position towards comVector
|
|
double linkDiagonal = dPtr->parent->GetBoundingBox().GetSize().GetLength();
|
|
dPtr->torqueVisual->SetPosition(normVec*linkDiagonal*0.75 + dPtr->comVector);
|
|
dPtr->torqueLine->SetPoint(1,
|
|
ignition::math::Vector3d(0, 0,
|
|
-linkDiagonal*0.75) / dPtr->torqueVisual->GetScale().Ign());
|
|
|
|
// Rotation tool
|
|
dPtr->rotTool->SetPosition(dPtr->comVector);
|
|
if (!dPtr->rotatedByMouse)
|
|
dPtr->rotTool->SetRotation(quat);
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
void ApplyWrenchVisual::Resize()
|
|
{
|
|
ApplyWrenchVisualPrivate *dPtr =
|
|
reinterpret_cast<ApplyWrenchVisualPrivate *>(this->dataPtr);
|
|
|
|
if (!dPtr->parent || !dPtr->forceVisual || !dPtr->torqueVisual ||
|
|
!dPtr->rotTool)
|
|
{
|
|
gzwarn << "ApplyWrenchVisual is incomplete." << std::endl;
|
|
return;
|
|
}
|
|
|
|
// Protect force/torque visuals
|
|
std::lock_guard<std::mutex> lock(dPtr->mutex);
|
|
|
|
double linkSize = std::max(0.1,
|
|
dPtr->parent->GetBoundingBox().GetSize().GetLength());
|
|
|
|
// Force visual
|
|
dPtr->forceVisual->SetScale(ignition::math::Vector3d(2*linkSize,
|
|
2*linkSize,
|
|
2*linkSize));
|
|
|
|
// Torque visual
|
|
dPtr->torqueVisual->SetScale(ignition::math::Vector3d(linkSize,
|
|
linkSize,
|
|
linkSize));
|
|
|
|
// Rot tool
|
|
dPtr->rotTool->SetScale(ignition::math::Vector3d(0.75*linkSize,
|
|
0.75*linkSize,
|
|
0.75*linkSize));
|
|
|
|
// Texts
|
|
double fontSize = 0.1*linkSize;
|
|
dPtr->forceText.SetCharHeight(fontSize);
|
|
dPtr->torqueText.SetCharHeight(fontSize);
|
|
dPtr->forceText.SetBaseline(0.12*linkSize);
|
|
}
|
|
|
|
///////////////////////////////////////////////////
|
|
rendering::VisualPtr ApplyWrenchVisual::GetForceVisual() const
|
|
{
|
|
ApplyWrenchVisualPrivate *dPtr =
|
|
reinterpret_cast<ApplyWrenchVisualPrivate *>(this->dataPtr);
|
|
|
|
if (!dPtr->forceVisual)
|
|
{
|
|
gzerr << "Force visual not found, but it should exist." << std::endl;
|
|
return NULL;
|
|
}
|
|
|
|
std::lock_guard<std::mutex> lock(dPtr->mutex);
|
|
|
|
return dPtr->forceVisual;
|
|
}
|
|
|
|
///////////////////////////////////////////////////
|
|
rendering::VisualPtr ApplyWrenchVisual::GetTorqueVisual() const
|
|
{
|
|
ApplyWrenchVisualPrivate *dPtr =
|
|
reinterpret_cast<ApplyWrenchVisualPrivate *>(this->dataPtr);
|
|
|
|
if (!dPtr->torqueVisual)
|
|
{
|
|
gzerr << "Torque visual not found, but it should exist." << std::endl;
|
|
return NULL;
|
|
}
|
|
|
|
std::lock_guard<std::mutex> lock(dPtr->mutex);
|
|
|
|
return dPtr->torqueVisual;
|
|
}
|
|
|
|
///////////////////////////////////////////////////
|
|
rendering::SelectionObjPtr ApplyWrenchVisual::GetRotTool() const
|
|
{
|
|
ApplyWrenchVisualPrivate *dPtr =
|
|
reinterpret_cast<ApplyWrenchVisualPrivate *>(this->dataPtr);
|
|
|
|
if (!dPtr->rotTool)
|
|
{
|
|
gzerr << "Rot tool not found, but it should exist." << std::endl;
|
|
return NULL;
|
|
}
|
|
|
|
return dPtr->rotTool;
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
void ApplyWrenchVisual::SetMode(Mode _mode)
|
|
{
|
|
ApplyWrenchVisualPrivate *dPtr =
|
|
reinterpret_cast<ApplyWrenchVisualPrivate *>(this->dataPtr);
|
|
|
|
if (!dPtr->forceVisual || !dPtr->torqueVisual || !dPtr->rotTool)
|
|
{
|
|
gzerr << "Some visual is missing!" << std::endl;
|
|
return;
|
|
}
|
|
|
|
// Protect force/torque visuals
|
|
std::lock_guard<std::mutex> lock(dPtr->mutex);
|
|
|
|
if (_mode == Mode::FORCE)
|
|
{
|
|
dPtr->forceVisual->SetMaterial(dPtr->selectedMaterial);
|
|
dPtr->torqueVisual->SetMaterial(dPtr->unselectedMaterial);
|
|
|
|
dPtr->rotTool->SetHandleVisible(SelectionObj::ROT_Y, true);
|
|
dPtr->rotTool->SetHandleVisible(SelectionObj::ROT_Z, true);
|
|
|
|
this->UpdateForceVisual();
|
|
}
|
|
else if (_mode == Mode::TORQUE)
|
|
{
|
|
dPtr->torqueVisual->SetMaterial(dPtr->selectedMaterial);
|
|
dPtr->forceVisual->SetMaterial(dPtr->unselectedMaterial);
|
|
|
|
dPtr->rotTool->SetHandleVisible(SelectionObj::ROT_Y, true);
|
|
dPtr->rotTool->SetHandleVisible(SelectionObj::ROT_Z, true);
|
|
|
|
this->UpdateTorqueVisual();
|
|
}
|
|
else if (_mode == Mode::NONE)
|
|
{
|
|
// Dark visuals
|
|
dPtr->forceVisual->SetMaterial(dPtr->unselectedMaterial);
|
|
dPtr->torqueVisual->SetMaterial(dPtr->unselectedMaterial);
|
|
// hide rot
|
|
dPtr->rotTool->SetHandleVisible(SelectionObj::ROT_Y, false);
|
|
dPtr->rotTool->SetHandleVisible(SelectionObj::ROT_Z, false);
|
|
}
|
|
}
|