pxmlw6n2f/Gazebo_Distributed_TCP/gazebo/rendering/Scene.cc

3739 lines
108 KiB
C++
Raw Normal View History

2019-03-28 10:57:49 +08:00
/*
* 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 <functional>
#include <boost/lexical_cast.hpp>
#include "gazebo/rendering/skyx/include/SkyX.h"
#include "gazebo/rendering/ogre_gazebo.h"
#include "gazebo/msgs/msgs.hh"
#include "gazebo/common/Exception.hh"
#include "gazebo/common/Assert.hh"
#include "gazebo/common/Console.hh"
#include "gazebo/rendering/Road2d.hh"
#include "gazebo/rendering/Projector.hh"
#include "gazebo/rendering/Heightmap.hh"
#include "gazebo/rendering/RenderEvents.hh"
#include "gazebo/rendering/LaserVisual.hh"
#include "gazebo/rendering/SonarVisual.hh"
#include "gazebo/rendering/WrenchVisual.hh"
#include "gazebo/rendering/CameraVisual.hh"
#include "gazebo/rendering/LogicalCameraVisual.hh"
#include "gazebo/rendering/JointVisual.hh"
#include "gazebo/rendering/COMVisual.hh"
#include "gazebo/rendering/InertiaVisual.hh"
#include "gazebo/rendering/LinkFrameVisual.hh"
#include "gazebo/rendering/ContactVisual.hh"
#include "gazebo/rendering/Conversions.hh"
#include "gazebo/rendering/Light.hh"
#include "gazebo/rendering/Visual.hh"
#include "gazebo/rendering/RenderEngine.hh"
#include "gazebo/rendering/UserCamera.hh"
#include "gazebo/rendering/Camera.hh"
#include "gazebo/rendering/WideAngleCamera.hh"
#include "gazebo/rendering/DepthCamera.hh"
#include "gazebo/rendering/GpuLaser.hh"
#include "gazebo/rendering/Grid.hh"
#include "gazebo/rendering/OriginVisual.hh"
#include "gazebo/rendering/RFIDVisual.hh"
#include "gazebo/rendering/RFIDTagVisual.hh"
#include "gazebo/rendering/VideoVisual.hh"
#include "gazebo/rendering/TransmitterVisual.hh"
#include "gazebo/rendering/SelectionObj.hh"
#include "gazebo/rendering/RayQuery.hh"
#if OGRE_VERSION_MAJOR >= 1 && OGRE_VERSION_MINOR >= 8
#include "gazebo/rendering/deferred_shading/SSAOLogic.hh"
#include "gazebo/rendering/deferred_shading/GBufferSchemeHandler.hh"
#include "gazebo/rendering/deferred_shading/NullSchemeHandler.hh"
#include "gazebo/rendering/deferred_shading/MergeSchemeHandler.hh"
#include "gazebo/rendering/deferred_shading/DeferredLightCP.hh"
#endif
#include "gazebo/rendering/RTShaderSystem.hh"
#include "gazebo/transport/TransportIface.hh"
#include "gazebo/transport/Node.hh"
#include "gazebo/rendering/ScenePrivate.hh"
#include "gazebo/rendering/Scene.hh"
#ifdef HAVE_OCULUS
#include "gazebo/rendering/OculusCamera.hh"
#endif
using namespace gazebo;
using namespace rendering;
uint32_t ScenePrivate::idCounter = 0;
struct VisualMessageLess {
bool operator() (boost::shared_ptr<msgs::Visual const> _i,
boost::shared_ptr<msgs::Visual const> _j)
{
return _i->name().size() < _j->name().size();
}
} VisualMessageLessOp;
//////////////////////////////////////////////////
Scene::Scene()
: dataPtr(new ScenePrivate)
{
}
//////////////////////////////////////////////////
Scene::Scene(const std::string &_name, const bool _enableVisualizations,
const bool _isServer)
: dataPtr(new ScenePrivate)
{
// \todo: This is a hack. There is no guarantee (other than the
// improbability of creating an extreme number of visuals), that
// this contactVisId is unique.
this->dataPtr->contactVisId = GZ_UINT32_MAX;
this->dataPtr->initialized = false;
this->dataPtr->showCOMs = false;
this->dataPtr->showInertias = false;
this->dataPtr->showLinkFrames = false;
this->dataPtr->showCollisions = false;
this->dataPtr->showJoints = false;
this->dataPtr->transparent = false;
this->dataPtr->wireframe = false;
this->dataPtr->requestMsg = NULL;
this->dataPtr->enableVisualizations = _enableVisualizations;
this->dataPtr->node = transport::NodePtr(new transport::Node());
this->dataPtr->node->Init(_name);
this->dataPtr->id = ScenePrivate::idCounter++;
this->dataPtr->idString = std::to_string(this->dataPtr->id);
this->dataPtr->name = _name;
this->dataPtr->manager = NULL;
this->dataPtr->raySceneQuery = NULL;
this->dataPtr->skyx = NULL;
this->dataPtr->receiveMutex = new std::mutex();
this->dataPtr->connections.push_back(
event::Events::ConnectPreRender(std::bind(&Scene::PreRender, this)));
this->dataPtr->connections.push_back(
rendering::Events::ConnectToggleLayer(
std::bind(&Scene::ToggleLayer, this, std::placeholders::_1)));
this->dataPtr->sensorSub = this->dataPtr->node->Subscribe("~/sensor",
&Scene::OnSensorMsg, this, true);
this->dataPtr->visSub =
this->dataPtr->node->Subscribe("~/visual", &Scene::OnVisualMsg, this);
this->dataPtr->lightFactorySub =
this->dataPtr->node->Subscribe("~/factory/light",
&Scene::OnLightFactoryMsg, this);
this->dataPtr->lightModifySub =
this->dataPtr->node->Subscribe("~/light/modify",
&Scene::OnLightModifyMsg, this);
if (_isServer)
{
this->dataPtr->poseSub = this->dataPtr->node->Subscribe("~/pose/local/info",
&Scene::OnPoseMsg, this);
}
else
{
this->dataPtr->poseSub = this->dataPtr->node->Subscribe("~/pose/info",
&Scene::OnPoseMsg, this);
}
this->dataPtr->jointSub =
this->dataPtr->node->Subscribe("~/joint", &Scene::OnJointMsg, this);
this->dataPtr->skeletonPoseSub =
this->dataPtr->node->Subscribe("~/skeleton_pose/info",
&Scene::OnSkeletonPoseMsg, this);
this->dataPtr->skySub =
this->dataPtr->node->Subscribe("~/sky", &Scene::OnSkyMsg, this);
this->dataPtr->modelInfoSub = this->dataPtr->node->Subscribe("~/model/info",
&Scene::OnModelMsg, this);
this->dataPtr->requestPub =
this->dataPtr->node->Advertise<msgs::Request>("~/request");
this->dataPtr->requestSub = this->dataPtr->node->Subscribe("~/request",
&Scene::OnRequest, this);
this->dataPtr->responseSub = this->dataPtr->node->Subscribe("~/response",
&Scene::OnResponse, this, true);
this->dataPtr->sceneSub =
this->dataPtr->node->Subscribe("~/scene", &Scene::OnScene, this);
this->dataPtr->sdf.reset(new sdf::Element);
sdf::initFile("scene.sdf", this->dataPtr->sdf);
this->dataPtr->terrain = NULL;
this->dataPtr->selectedVis.reset();
this->dataPtr->sceneSimTimePosesApplied = common::Time();
this->dataPtr->sceneSimTimePosesReceived = common::Time();
}
//////////////////////////////////////////////////
void Scene::Clear()
{
this->dataPtr->node->Fini();
this->dataPtr->modelMsgs.clear();
this->dataPtr->visualMsgs.clear();
this->dataPtr->lightFactoryMsgs.clear();
this->dataPtr->lightModifyMsgs.clear();
this->dataPtr->poseMsgs.clear();
this->dataPtr->sceneMsgs.clear();
this->dataPtr->jointMsgs.clear();
this->dataPtr->linkMsgs.clear();
this->dataPtr->sensorMsgs.clear();
this->dataPtr->poseSub.reset();
this->dataPtr->jointSub.reset();
this->dataPtr->sensorSub.reset();
this->dataPtr->sceneSub.reset();
this->dataPtr->skeletonPoseSub.reset();
this->dataPtr->visSub.reset();
this->dataPtr->skySub.reset();
this->dataPtr->lightFactorySub.reset();
this->dataPtr->lightModifySub.reset();
this->dataPtr->requestSub.reset();
this->dataPtr->responseSub.reset();
this->dataPtr->modelInfoSub.reset();
this->dataPtr->responsePub.reset();
this->dataPtr->requestPub.reset();
this->dataPtr->joints.clear();
delete this->dataPtr->terrain;
this->dataPtr->terrain = NULL;
while (!this->dataPtr->visuals.empty())
this->RemoveVisual(this->dataPtr->visuals.begin()->first);
this->dataPtr->visuals.clear();
if (this->dataPtr->originVisual)
{
this->dataPtr->originVisual->Fini();
this->dataPtr->originVisual.reset();
}
if (this->dataPtr->worldVisual)
{
this->dataPtr->worldVisual->Fini();
this->dataPtr->worldVisual.reset();
}
while (!this->dataPtr->lights.empty())
if (this->dataPtr->lights.begin()->second)
this->RemoveLight(this->dataPtr->lights.begin()->second);
this->dataPtr->lights.clear();
for (uint32_t i = 0; i < this->dataPtr->grids.size(); ++i)
delete this->dataPtr->grids[i];
this->dataPtr->grids.clear();
for (unsigned int i = 0; i < this->dataPtr->cameras.size(); ++i)
this->dataPtr->cameras[i]->Fini();
this->dataPtr->cameras.clear();
for (unsigned int i = 0; i < this->dataPtr->userCameras.size(); ++i)
this->dataPtr->userCameras[i]->Fini();
this->dataPtr->userCameras.clear();
delete this->dataPtr->skyx;
this->dataPtr->skyx = NULL;
RTShaderSystem::Instance()->RemoveScene(this->Name());
this->dataPtr->connections.clear();
this->dataPtr->initialized = false;
}
//////////////////////////////////////////////////
Scene::~Scene()
{
delete this->dataPtr->requestMsg;
this->dataPtr->requestMsg = NULL;
delete this->dataPtr->receiveMutex;
this->dataPtr->receiveMutex = NULL;
// raySceneQuery deletion handled by ogre
this->dataPtr->raySceneQuery= NULL;
this->Clear();
this->dataPtr->sdf->Reset();
this->dataPtr->sdf.reset();
}
//////////////////////////////////////////////////
void Scene::Load(sdf::ElementPtr _sdf)
{
this->dataPtr->sdf->Copy(_sdf);
this->Load();
}
//////////////////////////////////////////////////
void Scene::Load()
{
this->dataPtr->initialized = false;
Ogre::Root *root = RenderEngine::Instance()->Root();
if (this->dataPtr->manager)
root->destroySceneManager(this->dataPtr->manager);
this->dataPtr->manager = root->createSceneManager(Ogre::ST_GENERIC);
this->dataPtr->manager->setAmbientLight(
Ogre::ColourValue(0.1, 0.1, 0.1, 0.1));
#if OGRE_VERSION_MAJOR > 1 || OGRE_VERSION_MINOR >= 9
this->dataPtr->manager->addRenderQueueListener(
RenderEngine::Instance()->OverlaySystem());
#endif
}
//////////////////////////////////////////////////
VisualPtr Scene::GetWorldVisual() const
{
return this->WorldVisual();
}
//////////////////////////////////////////////////
VisualPtr Scene::WorldVisual() const
{
return this->dataPtr->worldVisual;
}
//////////////////////////////////////////////////
void Scene::Init()
{
this->dataPtr->worldVisual.reset(new Visual("__world_node__",
shared_from_this()));
this->dataPtr->worldVisual->SetId(0);
this->dataPtr->visuals[0] = this->dataPtr->worldVisual;
// RTShader system self-enables if the render path type is FORWARD,
RTShaderSystem::Instance()->AddScene(shared_from_this());
RTShaderSystem::Instance()->ApplyShadows(shared_from_this());
if (RenderEngine::Instance()->GetRenderPathType() == RenderEngine::DEFERRED)
this->InitDeferredShading();
for (uint32_t i = 0; i < this->dataPtr->grids.size(); ++i)
this->dataPtr->grids[i]->Init();
// Create Sky. This initializes SkyX, and makes it invisible. A Sky
// message must be received (via a scene message or on the ~/sky topic).
try
{
this->SetSky();
}
catch(...)
{
gzerr << "Failed to create the sky\n";
}
// Create Fog
if (this->dataPtr->sdf->HasElement("fog"))
{
sdf::ElementPtr fogElem = this->dataPtr->sdf->GetElement("fog");
this->SetFog(fogElem->Get<std::string>("type"),
fogElem->Get<common::Color>("color"),
fogElem->Get<double>("density"),
fogElem->Get<double>("start"),
fogElem->Get<double>("end"));
}
// Create ray scene query
this->dataPtr->raySceneQuery =
this->dataPtr->manager->createRayQuery(Ogre::Ray());
this->dataPtr->raySceneQuery->setSortByDistance(true);
this->dataPtr->raySceneQuery->setQueryMask(
Ogre::SceneManager::ENTITY_TYPE_MASK);
// Force shadows on.
this->SetShadowsEnabled(true);
// Create origin visual
this->dataPtr->originVisual.reset(new OriginVisual("__WORLD_ORIGIN__",
this->dataPtr->worldVisual));
this->dataPtr->originVisual->Load();
this->dataPtr->requestPub->WaitForConnection();
this->dataPtr->requestMsg = msgs::CreateRequest("scene_info");
this->dataPtr->requestPub->Publish(*this->dataPtr->requestMsg);
Road2d *road = new Road2d();
road->Load(this->dataPtr->worldVisual);
}
//////////////////////////////////////////////////
bool Scene::GetInitialized() const
{
return this->Initialized();
}
//////////////////////////////////////////////////
bool Scene::Initialized() const
{
return this->dataPtr->initialized;
}
//////////////////////////////////////////////////
void Scene::InitDeferredShading()
{
#if OGRE_VERSION_MAJOR > 1 || OGRE_VERSION_MINOR >= 8
Ogre::CompositorManager &compMgr = Ogre::CompositorManager::getSingleton();
// Deferred Shading scheme handler
Ogre::MaterialManager::getSingleton().addListener(
new GBufferSchemeHandler(GBufferMaterialGenerator::GBT_FAT),
"DSGBuffer");
// Deferred Lighting scheme handlers
Ogre::MaterialManager::getSingleton().addListener(
new GBufferSchemeHandler(GBufferMaterialGenerator::GBT_NORMAL_AND_DEPTH),
"DLGBuffer");
Ogre::MaterialManager::getSingleton().addListener(
new MergeSchemeHandler(false), "DLMerge");
Ogre::MaterialManager::getSingleton().addListener(
new NullSchemeHandler, "NoGBuffer");
compMgr.registerCustomCompositionPass("DeferredShadingLight",
new DeferredLightCompositionPass<DeferredShading>);
compMgr.registerCustomCompositionPass("DeferredLightingLight",
new DeferredLightCompositionPass<DeferredLighting>);
compMgr.registerCompositorLogic("SSAOLogic", new SSAOLogic);
// Create and instance geometry for VPL
Ogre::MeshPtr VPLMesh =
Ogre::MeshManager::getSingleton().createManual("VPLMesh",
Ogre::ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME);
Ogre::SubMesh *submeshMesh = VPLMesh->createSubMesh();
submeshMesh->operationType = Ogre::RenderOperation::OT_TRIANGLE_LIST;
submeshMesh->indexData = new Ogre::IndexData();
submeshMesh->vertexData = new Ogre::VertexData();
submeshMesh->useSharedVertices = false;
VPLMesh->_setBoundingSphereRadius(10.8f);
VPLMesh->_setBounds(Ogre::AxisAlignedBox(
Ogre::Vector3(-10.8, -10.8, -10.8), Ogre::Vector3(10.8, 10.8, 10.8)));
GeomUtils::CreateSphere(submeshMesh->vertexData, submeshMesh->indexData,
1.0, 6, 6, false, false);
int numVPLs = 400;
Ogre::InstanceManager *im =
this->dataPtr->manager->createInstanceManager("VPL_InstanceMgr",
"VPLMesh", Ogre::ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME,
Ogre::InstanceManager::HWInstancingBasic, numVPLs, Ogre::IM_USEALL);
for (int i = 0; i < numVPLs; ++i)
{
// Ogre::InstancedEntity *new_entity =
im->createInstancedEntity("DeferredLighting/VPL");
}
im->setBatchesAsStaticAndUpdate(true);
#endif
}
//////////////////////////////////////////////////
Ogre::SceneManager *Scene::GetManager() const
{
return this->OgreSceneManager();
}
//////////////////////////////////////////////////
Ogre::SceneManager *Scene::OgreSceneManager() const
{
return this->dataPtr->manager;
}
//////////////////////////////////////////////////
std::string Scene::GetName() const
{
return this->Name();
}
//////////////////////////////////////////////////
std::string Scene::Name() const
{
return this->dataPtr->name;
}
//////////////////////////////////////////////////
void Scene::SetAmbientColor(const common::Color &_color)
{
this->dataPtr->sdf->GetElement("ambient")->Set(_color);
// Ambient lighting
if (this->dataPtr->manager &&
Conversions::Convert(this->dataPtr->manager->getAmbientLight()) != _color)
{
this->dataPtr->manager->setAmbientLight(Conversions::Convert(_color));
}
}
//////////////////////////////////////////////////
common::Color Scene::GetAmbientColor() const
{
return this->AmbientColor();
}
//////////////////////////////////////////////////
common::Color Scene::AmbientColor() const
{
return this->dataPtr->sdf->Get<common::Color>("ambient");
}
//////////////////////////////////////////////////
void Scene::SetBackgroundColor(const common::Color &_color)
{
this->dataPtr->sdf->GetElement("background")->Set(_color);
Ogre::ColourValue clr = Conversions::Convert(_color);
std::vector<CameraPtr>::iterator iter;
for (iter = this->dataPtr->cameras.begin();
iter != this->dataPtr->cameras.end(); ++iter)
{
// TODO do not merge forward. Changes are part of an ABI compatible fix
// for wideangle camera background color.
auto cam = boost::dynamic_pointer_cast<WideAngleCamera>(*iter);
if (cam)
cam->SetBackgroundColor(_color);
else if ((*iter)->OgreViewport() &&
(*iter)->OgreViewport()->getBackgroundColour() != clr)
(*iter)->OgreViewport()->setBackgroundColour(clr);
}
std::vector<UserCameraPtr>::iterator iter2;
for (iter2 = this->dataPtr->userCameras.begin();
iter2 != this->dataPtr->userCameras.end(); ++iter2)
{
if ((*iter2)->OgreViewport() &&
(*iter2)->OgreViewport()->getBackgroundColour() != clr)
{
(*iter2)->OgreViewport()->setBackgroundColour(clr);
}
}
}
//////////////////////////////////////////////////
common::Color Scene::GetBackgroundColor() const
{
return this->BackgroundColor();
}
//////////////////////////////////////////////////
common::Color Scene::BackgroundColor() const
{
return this->dataPtr->sdf->Get<common::Color>("background");
}
//////////////////////////////////////////////////
void Scene::CreateGrid(const uint32_t cell_count, const float cell_length,
const float line_width, const common::Color &color)
{
Grid *grid = new Grid(this, cell_count, cell_length, line_width, color);
if (this->dataPtr->manager)
grid->Init();
this->dataPtr->grids.push_back(grid);
}
//////////////////////////////////////////////////
Grid *Scene::GetGrid(const uint32_t index) const
{
if (index >= this->dataPtr->grids.size())
{
gzerr << "Scene::GetGrid() Invalid index\n";
return NULL;
}
return this->dataPtr->grids[index];
}
//////////////////////////////////////////////////
uint32_t Scene::GetGridCount() const
{
return this->GridCount();
}
//////////////////////////////////////////////////
uint32_t Scene::GridCount() const
{
return this->dataPtr->grids.size();
}
//////////////////////////////////////////////////
CameraPtr Scene::CreateCamera(const std::string &_name, const bool _autoRender)
{
CameraPtr camera(new Camera(_name, shared_from_this(), _autoRender));
this->dataPtr->cameras.push_back(camera);
return camera;
}
//////////////////////////////////////////////////
DepthCameraPtr Scene::CreateDepthCamera(const std::string &_name,
const bool _autoRender)
{
DepthCameraPtr camera(new DepthCamera(this->dataPtr->name + "::" + _name,
shared_from_this(), _autoRender));
this->dataPtr->cameras.push_back(camera);
return camera;
}
//////////////////////////////////////////////////
WideAngleCameraPtr Scene::CreateWideAngleCamera(const std::string &_name,
const bool _autoRender)
{
WideAngleCameraPtr camera(new WideAngleCamera(_name,
shared_from_this(), _autoRender));
this->dataPtr->cameras.push_back(camera);
return camera;
}
//////////////////////////////////////////////////
GpuLaserPtr Scene::CreateGpuLaser(const std::string &_name,
const bool _autoRender)
{
GpuLaserPtr camera(new GpuLaser(this->dataPtr->name + "::" + _name,
shared_from_this(), _autoRender));
this->dataPtr->cameras.push_back(camera);
return camera;
}
//////////////////////////////////////////////////
uint32_t Scene::GetCameraCount() const
{
return this->CameraCount();
}
//////////////////////////////////////////////////
uint32_t Scene::CameraCount() const
{
return this->dataPtr->cameras.size();
}
//////////////////////////////////////////////////
CameraPtr Scene::GetCamera(const uint32_t index) const
{
CameraPtr cam;
if (index < this->dataPtr->cameras.size())
cam = this->dataPtr->cameras[index];
return cam;
}
//////////////////////////////////////////////////
CameraPtr Scene::GetCamera(const std::string &_name) const
{
CameraPtr result;
std::vector<CameraPtr>::const_iterator iter;
for (iter = this->dataPtr->cameras.begin();
iter != this->dataPtr->cameras.end(); ++iter)
{
if ((*iter)->Name() == _name)
result = *iter;
}
return result;
}
#ifdef HAVE_OCULUS
//////////////////////////////////////////////////
OculusCameraPtr Scene::CreateOculusCamera(const std::string &_name)
{
OculusCameraPtr camera(new OculusCamera(_name, shared_from_this()));
if (camera->Ready())
{
camera->Load();
camera->Init();
this->dataPtr->oculusCameras.push_back(camera);
}
return camera;
}
//////////////////////////////////////////////////
uint32_t Scene::GetOculusCameraCount() const
{
return this->OculusCameraCount();
}
//////////////////////////////////////////////////
uint32_t Scene::OculusCameraCount() const
{
return this->dataPtr->oculusCameras.size();
}
#endif
//////////////////////////////////////////////////
UserCameraPtr Scene::CreateUserCamera(const std::string &_name,
const bool _stereoEnabled)
{
UserCameraPtr camera(new UserCamera(_name, shared_from_this(),
_stereoEnabled));
camera->Load();
camera->Init();
this->dataPtr->userCameras.push_back(camera);
return camera;
}
//////////////////////////////////////////////////
uint32_t Scene::GetUserCameraCount() const
{
return this->UserCameraCount();
}
//////////////////////////////////////////////////
uint32_t Scene::UserCameraCount() const
{
return this->dataPtr->userCameras.size();
}
//////////////////////////////////////////////////
UserCameraPtr Scene::GetUserCamera(const uint32_t index) const
{
UserCameraPtr cam;
if (index < this->dataPtr->userCameras.size())
cam = this->dataPtr->userCameras[index];
return cam;
}
//////////////////////////////////////////////////
void Scene::RemoveCamera(const std::string &_name)
{
for (auto iter = this->dataPtr->cameras.begin();
iter != this->dataPtr->cameras.end(); ++iter)
{
if ((*iter)->Name() == _name)
{
(*iter)->Fini();
(*iter).reset();
this->dataPtr->cameras.erase(iter);
break;
}
}
}
//////////////////////////////////////////////////
LightPtr Scene::GetLight(const std::string &_name) const
{
LightPtr result;
std::string n = this->StripSceneName(_name);
Light_M::const_iterator iter = this->dataPtr->lights.find(n);
if (iter != this->dataPtr->lights.end())
result = iter->second;
return result;
}
//////////////////////////////////////////////////
uint32_t Scene::GetLightCount() const
{
return this->LightCount();
}
//////////////////////////////////////////////////
uint32_t Scene::LightCount() const
{
return this->dataPtr->lights.size();
}
//////////////////////////////////////////////////
LightPtr Scene::GetLight(const uint32_t _index) const
{
LightPtr result;
if (_index < this->dataPtr->lights.size())
{
Light_M::const_iterator iter = this->dataPtr->lights.begin();
std::advance(iter, _index);
result = iter->second;
}
else
{
gzerr << "Error: light index(" << _index << ") larger than light count("
<< this->dataPtr->lights.size() << "\n";
}
return result;
}
//////////////////////////////////////////////////
VisualPtr Scene::GetVisual(const uint32_t _id) const
{
Visual_M::const_iterator iter = this->dataPtr->visuals.find(_id);
if (iter != this->dataPtr->visuals.end())
return iter->second;
return VisualPtr();
}
//////////////////////////////////////////////////
VisualPtr Scene::GetVisual(const std::string &_name) const
{
VisualPtr result;
Visual_M::const_iterator iter;
for (iter = this->dataPtr->visuals.begin();
iter != this->dataPtr->visuals.end(); ++iter)
{
if (iter->second->GetName() == _name)
break;
}
if (iter != this->dataPtr->visuals.end())
result = iter->second;
else
{
std::string otherName = this->Name() + "::" + _name;
for (iter = this->dataPtr->visuals.begin();
iter != this->dataPtr->visuals.end(); ++iter)
{
if (iter->second->GetName() == otherName)
break;
}
if (iter != this->dataPtr->visuals.end())
result = iter->second;
}
return result;
}
//////////////////////////////////////////////////
uint32_t Scene::GetVisualCount() const
{
return this->VisualCount();
}
//////////////////////////////////////////////////
uint32_t Scene::VisualCount() const
{
return this->dataPtr->visuals.size();
}
//////////////////////////////////////////////////
void Scene::SelectVisual(const std::string &_name, const std::string &_mode)
{
this->dataPtr->selectedVis = this->GetVisual(_name);
this->dataPtr->selectionMode = _mode;
}
//////////////////////////////////////////////////
VisualPtr Scene::GetSelectedVisual() const
{
return this->SelectedVisual();
}
//////////////////////////////////////////////////
VisualPtr Scene::SelectedVisual() const
{
return this->dataPtr->selectedVis;
}
//////////////////////////////////////////////////
VisualPtr Scene::GetVisualAt(CameraPtr _camera,
const math::Vector2i &_mousePos,
std::string &_mod)
{
return this->VisualAt(_camera, _mousePos.Ign(), _mod);
}
//////////////////////////////////////////////////
VisualPtr Scene::VisualAt(CameraPtr _camera,
const ignition::math::Vector2i &_mousePos,
std::string &_mod)
{
VisualPtr visual;
Ogre::Entity *closestEntity = this->OgreEntityAt(_camera, _mousePos, false);
_mod = "";
if (closestEntity)
{
// Make sure we set the _mod only if we have found a selection object
if (closestEntity->getName().substr(0, 15) == "__SELECTION_OBJ" &&
closestEntity->getUserObjectBindings().getUserAny().getType()
== typeid(std::string))
{
try
{
_mod = Ogre::any_cast<std::string>(
closestEntity->getUserObjectBindings().getUserAny());
}
catch(boost::bad_any_cast &e)
{
gzerr << "boost any_cast error:" << e.what() << "\n";
}
}
try
{
visual = this->GetVisual(Ogre::any_cast<std::string>(
closestEntity->getUserObjectBindings().getUserAny()));
}
catch(boost::bad_any_cast &e)
{
gzerr << "boost any_cast error:" << e.what() << "\n";
}
}
return visual;
}
//////////////////////////////////////////////////
VisualPtr Scene::GetModelVisualAt(CameraPtr _camera,
const math::Vector2i &_mousePos)
{
return this->ModelVisualAt(_camera, _mousePos.Ign());
}
//////////////////////////////////////////////////
VisualPtr Scene::ModelVisualAt(CameraPtr _camera,
const ignition::math::Vector2i &_mousePos)
{
VisualPtr vis = this->VisualAt(_camera, _mousePos);
if (vis)
vis = this->GetVisual(vis->GetName().substr(0, vis->GetName().find("::")));
return vis;
}
//////////////////////////////////////////////////
void Scene::SnapVisualToNearestBelow(const std::string &_visualName)
{
VisualPtr visBelow = this->VisualBelow(_visualName);
VisualPtr vis = this->GetVisual(_visualName);
if (vis && visBelow)
{
math::Vector3 pos = vis->GetWorldPose().pos;
double dz = vis->GetBoundingBox().min.z - visBelow->GetBoundingBox().max.z;
pos.z -= dz;
vis->SetWorldPosition(pos);
}
}
//////////////////////////////////////////////////
VisualPtr Scene::GetVisualBelow(const std::string &_visualName)
{
return this->VisualBelow(_visualName);
}
//////////////////////////////////////////////////
VisualPtr Scene::VisualBelow(const std::string &_visualName)
{
VisualPtr result;
VisualPtr vis = this->GetVisual(_visualName);
if (vis)
{
std::vector<VisualPtr> below;
this->VisualsBelowPoint(vis->GetWorldPose().pos.Ign(), below);
double maxZ = -10000;
for (uint32_t i = 0; i < below.size(); ++i)
{
if (below[i]->GetName().find(vis->GetName()) != 0
&& below[i]->GetBoundingBox().max.z > maxZ)
{
maxZ = below[i]->GetBoundingBox().max.z;
result = below[i];
}
}
}
return result;
}
//////////////////////////////////////////////////
double Scene::GetHeightBelowPoint(const math::Vector3 &_pt)
{
return this->HeightBelowPoint(_pt.Ign());
}
//////////////////////////////////////////////////
double Scene::HeightBelowPoint(const ignition::math::Vector3d &_pt)
{
double height = 0;
Ogre::Ray ray(Conversions::Convert(_pt), Ogre::Vector3(0, 0, -1));
if (!this->dataPtr->raySceneQuery)
{
this->dataPtr->raySceneQuery =
this->dataPtr->manager->createRayQuery(Ogre::Ray());
}
this->dataPtr->raySceneQuery->setRay(ray);
this->dataPtr->raySceneQuery->setSortByDistance(true, 0);
// Perform the scene query
Ogre::RaySceneQueryResult &result = this->dataPtr->raySceneQuery->execute();
Ogre::RaySceneQueryResult::iterator iter;
for (iter = result.begin(); iter != result.end(); ++iter)
{
// is the result a MovableObject
if (iter->movable && iter->movable->getMovableType().compare("Entity") == 0)
{
if (!iter->movable->isVisible() ||
iter->movable->getName().find("__COLLISION_VISUAL__") !=
std::string::npos)
continue;
if (iter->movable->getName().substr(0, 15) == "__SELECTION_OBJ")
continue;
height = _pt.Z() - iter->distance;
break;
}
}
// The default ray scene query does not work with terrain, so we have to
// check ourselves.
if (this->dataPtr->terrain)
{
double terrainHeight =
this->dataPtr->terrain->Height(_pt.X(), _pt.Y(), _pt.Z());
if (terrainHeight <= _pt.Z())
height = std::max(height, terrainHeight);
}
return height;
}
//////////////////////////////////////////////////
void Scene::GetVisualsBelowPoint(const math::Vector3 &_pt,
std::vector<VisualPtr> &_visuals)
{
return this->VisualsBelowPoint(_pt.Ign(), _visuals);
}
//////////////////////////////////////////////////
void Scene::VisualsBelowPoint(const ignition::math::Vector3d &_pt,
std::vector<VisualPtr> &_visuals)
{
Ogre::Ray ray(Conversions::Convert(_pt), Ogre::Vector3(0, 0, -1));
if (!this->dataPtr->raySceneQuery)
{
this->dataPtr->raySceneQuery =
this->dataPtr->manager->createRayQuery(Ogre::Ray());
}
this->dataPtr->raySceneQuery->setRay(ray);
this->dataPtr->raySceneQuery->setSortByDistance(true, 0);
// Perform the scene query
Ogre::RaySceneQueryResult &result = this->dataPtr->raySceneQuery->execute();
Ogre::RaySceneQueryResult::iterator iter = result.begin();
_visuals.clear();
for (iter = result.begin(); iter != result.end(); ++iter)
{
// is the result a MovableObject
if (iter->movable && iter->movable->getMovableType().compare("Entity") == 0)
{
if (!iter->movable->isVisible() ||
iter->movable->getName().find("__COLLISION_VISUAL__") !=
std::string::npos)
continue;
if (iter->movable->getName().substr(0, 15) == "__SELECTION_OBJ")
continue;
Ogre::Entity *ogreEntity = static_cast<Ogre::Entity*>(iter->movable);
if (ogreEntity)
{
try
{
VisualPtr v = this->GetVisual(Ogre::any_cast<std::string>(
ogreEntity->getUserObjectBindings().getUserAny()));
if (v)
_visuals.push_back(v);
}
catch(boost::bad_any_cast &e)
{
gzerr << "boost any_cast error:" << e.what() << "\n";
}
}
}
}
}
//////////////////////////////////////////////////
VisualPtr Scene::GetVisualAt(CameraPtr _camera,
const math::Vector2i &_mousePos)
{
return this->VisualAt(_camera, _mousePos.Ign());
}
//////////////////////////////////////////////////
VisualPtr Scene::VisualAt(CameraPtr _camera,
const ignition::math::Vector2i &_mousePos)
{
VisualPtr visual;
Ogre::Entity *closestEntity = this->OgreEntityAt(_camera,
_mousePos, true);
if (closestEntity)
{
try
{
visual = this->GetVisual(Ogre::any_cast<std::string>(
closestEntity->getUserObjectBindings().getUserAny()));
}
catch(boost::bad_any_cast &e)
{
gzerr << "boost any_cast error:" << e.what() << "\n";
}
}
return visual;
}
/////////////////////////////////////////////////
Ogre::Entity *Scene::OgreEntityAt(CameraPtr _camera,
const ignition::math::Vector2i &_mousePos,
const bool _ignoreSelectionObj)
{
Ogre::Camera *ogreCam = _camera->OgreCamera();
Ogre::Real closest_distance = -1.0f;
Ogre::Ray mouseRay = ogreCam->getCameraToViewportRay(
static_cast<float>(_mousePos.X()) /
ogreCam->getViewport()->getActualWidth(),
static_cast<float>(_mousePos.Y()) /
ogreCam->getViewport()->getActualHeight());
this->dataPtr->raySceneQuery->setRay(mouseRay);
// Perform the scene query
Ogre::RaySceneQueryResult &result = this->dataPtr->raySceneQuery->execute();
Ogre::RaySceneQueryResult::iterator iter = result.begin();
Ogre::Entity *closestEntity = NULL;
for (iter = result.begin(); iter != result.end(); ++iter)
{
// is the result a MovableObject
if (iter->movable && iter->movable->getMovableType().compare("Entity") == 0)
{
if (!iter->movable->isVisible() ||
iter->movable->getName().find("__COLLISION_VISUAL__") !=
std::string::npos)
continue;
if (_ignoreSelectionObj &&
iter->movable->getName().substr(0, 15) == "__SELECTION_OBJ")
continue;
Ogre::Entity *ogreEntity = static_cast<Ogre::Entity*>(iter->movable);
// mesh data to retrieve
size_t vertex_count;
size_t index_count;
Ogre::Vector3 *vertices;
uint64_t *indices;
// Get the mesh information
this->MeshInformation(ogreEntity->getMesh().get(), vertex_count,
vertices, index_count, indices,
Conversions::ConvertIgn(
ogreEntity->getParentNode()->_getDerivedPosition()),
Conversions::ConvertIgn(
ogreEntity->getParentNode()->_getDerivedOrientation()),
Conversions::ConvertIgn(
ogreEntity->getParentNode()->_getDerivedScale()));
bool new_closest_found = false;
for (int i = 0; i < static_cast<int>(index_count); i += 3)
{
// when indices size is not divisible by 3
if (i+2 >= static_cast<int>(index_count))
break;
// check for a hit against this triangle
std::pair<bool, Ogre::Real> hit = Ogre::Math::intersects(mouseRay,
vertices[indices[i]],
vertices[indices[i+1]],
vertices[indices[i+2]],
true, false);
// if it was a hit check if its the closest
if (hit.first)
{
if ((closest_distance < 0.0f) || (hit.second < closest_distance))
{
// this is the closest so far, save it off
closest_distance = hit.second;
new_closest_found = true;
}
}
}
delete [] vertices;
delete [] indices;
if (new_closest_found)
{
closestEntity = ogreEntity;
// break;
}
}
}
return closestEntity;
}
//////////////////////////////////////////////////
bool Scene::GetFirstContact(CameraPtr _camera,
const math::Vector2i &_mousePos,
math::Vector3 &_position)
{
ignition::math::Vector3d position;
bool result = this->FirstContact(_camera, _mousePos.Ign(), position);
_position = position;
return result;
}
//////////////////////////////////////////////////
bool Scene::FirstContact(CameraPtr _camera,
const ignition::math::Vector2i &_mousePos,
ignition::math::Vector3d &_position)
{
_position = ignition::math::Vector3d::Zero;
double distance = -1.0;
Ogre::Camera *ogreCam = _camera->OgreCamera();
Ogre::Ray mouseRay = ogreCam->getCameraToViewportRay(
static_cast<float>(_mousePos.X()) /
ogreCam->getViewport()->getActualWidth(),
static_cast<float>(_mousePos.Y()) /
ogreCam->getViewport()->getActualHeight());
UserCameraPtr userCam = boost::dynamic_pointer_cast<UserCamera>(_camera);
if (userCam)
{
VisualPtr vis = userCam->GetVisual(_mousePos);
if (vis)
{
RayQuery rayQuery(_camera);
math::Vector3 intersect;
std::vector<math::Vector3> vertices;
rayQuery.SelectMeshTriangle(_mousePos.X(), _mousePos.Y(), vis,
intersect, vertices);
distance = Conversions::ConvertIgn(mouseRay.getOrigin()).Distance(
intersect.Ign());
}
}
else
{
this->dataPtr->raySceneQuery->setSortByDistance(true);
this->dataPtr->raySceneQuery->setRay(mouseRay);
// Perform the scene query
Ogre::RaySceneQueryResult &result = this->dataPtr->raySceneQuery->execute();
Ogre::RaySceneQueryResult::iterator iter = result.begin();
// Iterate over all the results.
for (; iter != result.end() && distance <= 0.0; ++iter)
{
// Skip results where the distance is zero or less
if (iter->distance <= 0.0)
continue;
unsigned int flags = iter->movable->getVisibilityFlags();
// Only accept a hit if there is an entity and not a gui visual
// and not a selection-only object (e.g. light selection ent)
const bool guiOrSelectable = (flags & GZ_VISIBILITY_GUI)
|| (flags & GZ_VISIBILITY_SELECTABLE);
if (iter->movable && iter->movable->getVisible() &&
iter->movable->getMovableType().compare("Entity") == 0 &&
!(flags != GZ_VISIBILITY_ALL && guiOrSelectable))
{
Ogre::Entity *ogreEntity = static_cast<Ogre::Entity*>(iter->movable);
VisualPtr vis;
if (!ogreEntity->getUserObjectBindings().getUserAny().isEmpty())
{
try
{
vis = this->GetVisual(Ogre::any_cast<std::string>(
ogreEntity->getUserObjectBindings().getUserAny()));
}
catch(Ogre::Exception &e)
{
gzerr << "Ogre Error:" << e.getFullDescription() << "\n";
continue;
}
if (!vis)
continue;
RayQuery rayQuery(_camera);
math::Vector3 intersect;
std::vector<math::Vector3> vertices;
if (rayQuery.SelectMeshTriangle(_mousePos.X(), _mousePos.Y(), vis,
intersect, vertices))
{
distance = Conversions::ConvertIgn(mouseRay.getOrigin()).Distance(
intersect.Ign());
}
}
}
}
}
// Check intersection with the terrain
if (this->dataPtr->terrain)
{
// The terrain uses a special ray intersection test.
Ogre::TerrainGroup::RayResult terrainResult =
this->dataPtr->terrain->OgreTerrain()->rayIntersects(mouseRay);
if (terrainResult.hit)
{
double terrainHitDist =
mouseRay.getOrigin().distance(terrainResult.position);
if (terrainHitDist > 0.0 &&
(distance <= 0.0 || terrainHitDist < distance))
{
_position = Conversions::ConvertIgn(terrainResult.position);
return true;
}
}
}
// if no terrain intersection, return position of intersection point with
// closest entity
if (distance > 0.0)
{
_position = Conversions::ConvertIgn(mouseRay.getPoint(distance));
return true;
}
return false;
}
//////////////////////////////////////////////////
void Scene::PrintSceneGraph()
{
this->PrintSceneGraphHelper("", this->dataPtr->manager->getRootSceneNode());
}
//////////////////////////////////////////////////
void Scene::PrintSceneGraphHelper(const std::string &prefix_, Ogre::Node *node_)
{
Ogre::SceneNode *snode = dynamic_cast<Ogre::SceneNode*>(node_);
std::string nodeName = node_->getName();
int numAttachedObjs = 0;
bool isInSceneGraph = false;
if (snode)
{
numAttachedObjs = snode->numAttachedObjects();
isInSceneGraph = snode->isInSceneGraph();
}
else
{
gzerr << "Invalid SceneNode\n";
return;
}
int numChildren = node_->numChildren();
Ogre::Vector3 pos = node_->getPosition();
Ogre::Vector3 scale = node_->getScale();
std::cout << prefix_ << nodeName << "\n";
std::cout << prefix_ << " Num Objs[" << numAttachedObjs << "]\n";
for (int i = 0; i < numAttachedObjs; ++i)
{
std::cout << prefix_
<< " Obj[" << snode->getAttachedObject(i)->getName() << "]\n";
}
std::cout << prefix_ << " Num Children[" << numChildren << "]\n";
std::cout << prefix_ << " IsInGraph[" << isInSceneGraph << "]\n";
std::cout << prefix_
<< " Pos[" << pos.x << " " << pos.y << " " << pos.z << "]\n";
std::cout << prefix_
<< " Scale[" << scale.x << " " << scale.y << " " << scale.z << "]\n";
for (uint32_t i = 0; i < node_->numChildren(); ++i)
{
this->PrintSceneGraphHelper(prefix_ + " ", node_->getChild(i));
}
}
//////////////////////////////////////////////////
void Scene::DrawLine(const math::Vector3 &_start,
const math::Vector3 &_end,
const std::string &_name)
{
this->DrawLine(_start.Ign(), _end.Ign(), _name);
}
//////////////////////////////////////////////////
void Scene::DrawLine(const ignition::math::Vector3d &_start,
const ignition::math::Vector3d &_end,
const std::string &_name)
{
Ogre::SceneNode *sceneNode = NULL;
Ogre::ManualObject *obj = NULL;
bool attached = false;
if (this->dataPtr->manager->hasManualObject(_name))
{
sceneNode = this->dataPtr->manager->getSceneNode(_name);
obj = this->dataPtr->manager->getManualObject(_name);
attached = true;
}
else
{
sceneNode =
this->dataPtr->manager->getRootSceneNode()->createChildSceneNode(_name);
obj = this->dataPtr->manager->createManualObject(_name);
}
sceneNode->setVisible(true);
obj->setVisible(true);
obj->clear();
obj->begin("Gazebo/Red", Ogre::RenderOperation::OT_LINE_LIST);
obj->position(_start.X(), _start.Y(), _start.Z());
obj->position(_end.X(), _end.Y(), _end.Z());
obj->end();
if (!attached)
sceneNode->attachObject(obj);
}
//////////////////////////////////////////////////
void Scene::SetFog(const std::string &_type, const common::Color &_color,
const double _density, const double _start,
const double _end)
{
Ogre::FogMode fogType = Ogre::FOG_NONE;
if (_type == "linear")
fogType = Ogre::FOG_LINEAR;
else if (_type == "exp")
fogType = Ogre::FOG_EXP;
else if (_type == "exp2")
fogType = Ogre::FOG_EXP2;
sdf::ElementPtr elem = this->dataPtr->sdf->GetElement("fog");
elem->GetElement("type")->Set(_type);
elem->GetElement("color")->Set(_color);
elem->GetElement("density")->Set(_density);
elem->GetElement("start")->Set(_start);
elem->GetElement("end")->Set(_end);
if (this->dataPtr->manager)
this->dataPtr->manager->setFog(fogType, Conversions::Convert(_color),
_density, _start, _end);
}
//////////////////////////////////////////////////
void Scene::SetVisible(const std::string &_name, const bool _visible)
{
if (this->dataPtr->manager->hasSceneNode(_name))
this->dataPtr->manager->getSceneNode(_name)->setVisible(_visible);
if (this->dataPtr->manager->hasManualObject(_name))
this->dataPtr->manager->getManualObject(_name)->setVisible(_visible);
}
//////////////////////////////////////////////////
uint32_t Scene::GetId() const
{
return this->Id();
}
//////////////////////////////////////////////////
uint32_t Scene::Id() const
{
return this->dataPtr->id;
}
//////////////////////////////////////////////////
std::string Scene::GetIdString() const
{
return this->IdString();
}
//////////////////////////////////////////////////
std::string Scene::IdString() const
{
return this->dataPtr->idString;
}
//////////////////////////////////////////////////
void Scene::MeshInformation(const Ogre::Mesh *_mesh,
size_t &_vertex_count,
Ogre::Vector3* &_vertices,
size_t &_index_count,
uint64_t* &_indices,
const ignition::math::Vector3d &_position,
const ignition::math::Quaterniond &_orient,
const ignition::math::Vector3d &_scale)
{
bool added_shared = false;
size_t current_offset = 0;
size_t next_offset = 0;
size_t index_offset = 0;
_vertex_count = _index_count = 0;
// Calculate how many vertices and indices we're going to need
for (uint16_t i = 0; i < _mesh->getNumSubMeshes(); ++i)
{
Ogre::SubMesh* submesh = _mesh->getSubMesh(i);
// We only need to add the shared vertices once
if (submesh->useSharedVertices)
{
if (!added_shared)
{
_vertex_count += _mesh->sharedVertexData->vertexCount;
added_shared = true;
}
}
else
{
_vertex_count += submesh->vertexData->vertexCount;
}
// Add the indices
_index_count += submesh->indexData->indexCount;
}
// Allocate space for the vertices and indices
_vertices = new Ogre::Vector3[_vertex_count];
_indices = new uint64_t[_index_count];
added_shared = false;
// Run through the submeshes again, adding the data into the arrays
for (uint16_t i = 0; i < _mesh->getNumSubMeshes(); ++i)
{
Ogre::SubMesh* submesh = _mesh->getSubMesh(i);
Ogre::VertexData* vertex_data = submesh->useSharedVertices ?
_mesh->sharedVertexData : submesh->vertexData;
if (!submesh->useSharedVertices || !added_shared)
{
if (submesh->useSharedVertices)
{
added_shared = true;
}
const Ogre::VertexElement* posElem =
vertex_data->vertexDeclaration->findElementBySemantic(
Ogre::VES_POSITION);
Ogre::HardwareVertexBufferSharedPtr vbuf =
vertex_data->vertexBufferBinding->getBuffer(posElem->getSource());
unsigned char *vertex =
static_cast<unsigned char*>(
vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
// There is _no_ baseVertexPointerToElement() which takes an
// Ogre::Real or a double as second argument. So make it float,
// to avoid trouble when Ogre::Real will be comiled/typedefed as double:
// Ogre::Real* pReal;
float *pReal;
for (size_t j = 0; j < vertex_data->vertexCount;
++j, vertex += vbuf->getVertexSize())
{
posElem->baseVertexPointerToElement(vertex, &pReal);
ignition::math::Vector3d pt(pReal[0], pReal[1], pReal[2]);
_vertices[current_offset + j] =
Conversions::Convert((_orient * (pt * _scale)) + _position);
}
vbuf->unlock();
next_offset += vertex_data->vertexCount;
}
Ogre::IndexData* index_data = submesh->indexData;
Ogre::HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer;
if ((ibuf->getType() == Ogre::HardwareIndexBuffer::IT_32BIT))
{
uint32_t* pLong = static_cast<uint32_t*>(
ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
for (size_t k = 0; k < index_data->indexCount; k++)
{
_indices[index_offset++] = pLong[k];
}
}
else
{
uint64_t* pLong = static_cast<uint64_t*>(
ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
uint16_t* pShort = reinterpret_cast<uint16_t*>(pLong);
for (size_t k = 0; k < index_data->indexCount; k++)
{
_indices[index_offset++] = static_cast<uint64_t>(pShort[k]);
}
}
ibuf->unlock();
current_offset = next_offset;
}
}
/////////////////////////////////////////////////
bool Scene::ProcessSceneMsg(ConstScenePtr &_msg)
{
{
std::lock_guard<std::recursive_mutex> lock(this->dataPtr->poseMsgMutex);
for (int i = 0; i < _msg->model_size(); ++i)
{
PoseMsgs_M::iterator iter =
this->dataPtr->poseMsgs.find(_msg->model(i).id());
if (iter != this->dataPtr->poseMsgs.end())
iter->second.CopyFrom(_msg->model(i).pose());
else
this->dataPtr->poseMsgs.insert(
std::make_pair(_msg->model(i).id(), _msg->model(i).pose()));
this->dataPtr->poseMsgs[_msg->model(i).id()].set_name(
_msg->model(i).name());
this->dataPtr->poseMsgs[_msg->model(i).id()].set_id(_msg->model(i).id());
this->ProcessModelMsg(_msg->model(i));
}
}
for (int i = 0; i < _msg->light_size(); ++i)
{
boost::shared_ptr<msgs::Light> lm(new msgs::Light(_msg->light(i)));
this->dataPtr->lightFactoryMsgs.push_back(lm);
}
for (int i = 0; i < _msg->joint_size(); ++i)
{
boost::shared_ptr<msgs::Joint> jm(new msgs::Joint(_msg->joint(i)));
this->dataPtr->jointMsgs.push_back(jm);
}
if (_msg->has_ambient())
this->SetAmbientColor(msgs::Convert(_msg->ambient()));
if (_msg->has_background())
this->SetBackgroundColor(msgs::Convert(_msg->background()));
if (_msg->has_shadows())
this->SetShadowsEnabled(_msg->shadows());
if (_msg->has_grid())
this->SetGrid(_msg->grid());
if (_msg->has_origin_visual())
this->ShowOrigin(_msg->origin_visual());
// Process the sky message.
if (_msg->has_sky())
{
boost::shared_ptr<msgs::Sky> sm(new msgs::Sky(_msg->sky()));
this->OnSkyMsg(sm);
}
if (_msg->has_fog())
{
sdf::ElementPtr elem = this->dataPtr->sdf->GetElement("fog");
if (_msg->fog().has_color())
elem->GetElement("color")->Set(
msgs::Convert(_msg->fog().color()));
if (_msg->fog().has_density())
elem->GetElement("density")->Set(_msg->fog().density());
if (_msg->fog().has_start())
elem->GetElement("start")->Set(_msg->fog().start());
if (_msg->fog().has_end())
elem->GetElement("end")->Set(_msg->fog().end());
if (_msg->fog().has_type())
{
std::string type;
if (_msg->fog().type() == msgs::Fog::LINEAR)
type = "linear";
else if (_msg->fog().type() == msgs::Fog::EXPONENTIAL)
type = "exp";
else if (_msg->fog().type() == msgs::Fog::EXPONENTIAL2)
type = "exp2";
else
type = "none";
elem->GetElement("type")->Set(type);
}
this->SetFog(elem->Get<std::string>("type"),
elem->Get<common::Color>("color"),
elem->Get<double>("density"),
elem->Get<double>("start"),
elem->Get<double>("end"));
}
return true;
}
//////////////////////////////////////////////////
bool Scene::ProcessModelMsg(const msgs::Model &_msg)
{
std::string modelName, linkName;
modelName = _msg.name() + "::";
for (int j = 0; j < _msg.visual_size(); ++j)
{
boost::shared_ptr<msgs::Visual> vm(new msgs::Visual(
_msg.visual(j)));
this->dataPtr->modelVisualMsgs.push_back(vm);
}
// Set the scale of the model visual
if (_msg.has_scale())
{
// update scale using a visual msg
boost::shared_ptr<msgs::Visual> vm(new msgs::Visual);
if (_msg.has_id())
vm->set_id(_msg.id());
if (_msg.has_name())
vm->set_name(_msg.name());
vm->mutable_scale()->set_x(_msg.scale().x());
vm->mutable_scale()->set_y(_msg.scale().y());
vm->mutable_scale()->set_z(_msg.scale().z());
this->dataPtr->modelVisualMsgs.push_back(vm);
}
for (int j = 0; j < _msg.joint_size(); ++j)
{
boost::shared_ptr<msgs::Joint> jm(new msgs::Joint(
_msg.joint(j)));
this->dataPtr->jointMsgs.push_back(jm);
for (int k = 0; k < _msg.joint(j).sensor_size(); ++k)
{
boost::shared_ptr<msgs::Sensor> sm(new msgs::Sensor(
_msg.joint(j).sensor(k)));
this->dataPtr->sensorMsgs.push_back(sm);
}
}
for (int j = 0; j < _msg.link_size(); ++j)
{
linkName = modelName + _msg.link(j).name();
{
std::lock_guard<std::recursive_mutex> lock(this->dataPtr->poseMsgMutex);
if (_msg.link(j).has_pose())
{
PoseMsgs_M::iterator iter =
this->dataPtr->poseMsgs.find(_msg.link(j).id());
if (iter != this->dataPtr->poseMsgs.end())
iter->second.CopyFrom(_msg.link(j).pose());
else
this->dataPtr->poseMsgs.insert(
std::make_pair(_msg.link(j).id(), _msg.link(j).pose()));
this->dataPtr->poseMsgs[_msg.link(j).id()].set_name(linkName);
this->dataPtr->poseMsgs[_msg.link(j).id()].set_id(_msg.link(j).id());
}
}
if (_msg.link(j).has_inertial())
{
boost::shared_ptr<msgs::Link> lm(new msgs::Link(_msg.link(j)));
this->dataPtr->linkMsgs.push_back(lm);
}
if (_msg.link(j).visual_size() > 0)
{
// note: the first visual in the link is the link visual
msgs::VisualPtr vm(new msgs::Visual(
_msg.link(j).visual(0)));
this->dataPtr->linkVisualMsgs.push_back(vm);
}
for (int k = 1; k < _msg.link(j).visual_size(); ++k)
{
boost::shared_ptr<msgs::Visual> vm(new msgs::Visual(
_msg.link(j).visual(k)));
this->dataPtr->visualMsgs.push_back(vm);
}
for (int k = 0; k < _msg.link(j).collision_size(); ++k)
{
for (int l = 0;
l < _msg.link(j).collision(k).visual_size(); l++)
{
boost::shared_ptr<msgs::Visual> vm(new msgs::Visual(
_msg.link(j).collision(k).visual(l)));
this->dataPtr->collisionVisualMsgs.push_back(vm);
}
}
for (int k = 0; k < _msg.link(j).sensor_size(); ++k)
{
boost::shared_ptr<msgs::Sensor> sm(new msgs::Sensor(
_msg.link(j).sensor(k)));
this->dataPtr->sensorMsgs.push_back(sm);
}
}
for (int i = 0; i < _msg.model_size(); ++i)
{
boost::shared_ptr<msgs::Model> mm(new msgs::Model(_msg.model(i)));
this->dataPtr->modelMsgs.push_back(mm);
}
return true;
}
//////////////////////////////////////////////////
void Scene::OnSensorMsg(ConstSensorPtr &_msg)
{
std::lock_guard<std::mutex> lock(*this->dataPtr->receiveMutex);
this->dataPtr->sensorMsgs.push_back(_msg);
}
//////////////////////////////////////////////////
void Scene::OnVisualMsg(ConstVisualPtr &_msg)
{
std::lock_guard<std::mutex> lock(*this->dataPtr->receiveMutex);
this->dataPtr->visualMsgs.push_back(_msg);
}
//////////////////////////////////////////////////
void Scene::PreRender()
{
/* Deferred shading debug code. Delete me soon (July 17, 2012)
static bool first = true;
if (!first)
{
Ogre::RenderSystem *renderSys =
this->dataPtr->manager->getDestinationRenderSystem();
Ogre::RenderSystem::RenderTargetIterator renderIter =
renderSys->getRenderTargetIterator();
int i = 0;
for (; renderIter.current() != renderIter.end(); renderIter.moveNext())
{
if (renderIter.current()->second->getNumViewports() > 0)
{
std::ostringstream filename, filename2;
filename << "/tmp/render_targets/iter_" << this->iterations
<< "_" << i << ".png";
filename2 << "/tmp/render_targets/iter_"
<< this->iterations << "_" << i << "_b.png";
Ogre::MultiRenderTarget *mtarget =
dynamic_cast<Ogre::MultiRenderTarget *>(
renderIter.current()->second);
if (mtarget)
{
// std::cout << renderIter.current()->first << "\n";
mtarget->getBoundSurface(0)->writeContentsToFile(filename.str());
mtarget->getBoundSurface(1)->writeContentsToFile(filename2.str());
++i;
}
else
{
renderIter.current()->second->writeContentsToFile(filename.str());
++i;
}
}
}
this->iterations++;
}
else
first = false;
*/
static RequestMsgs_L::iterator rIter;
static SceneMsgs_L::iterator sIter;
static ModelMsgs_L::iterator modelIter;
static VisualMsgs_L::iterator visualIter;
static LightMsgs_L::iterator lightIter;
static PoseMsgs_M::iterator pIter;
static SkeletonPoseMsgs_L::iterator spIter;
static JointMsgs_L::iterator jointIter;
static SensorMsgs_L::iterator sensorIter;
static LinkMsgs_L::iterator linkIter;
SceneMsgs_L sceneMsgsCopy;
ModelMsgs_L modelMsgsCopy;
SensorMsgs_L sensorMsgsCopy;
LightMsgs_L lightFactoryMsgsCopy;
LightMsgs_L lightModifyMsgsCopy;
VisualMsgs_L modelVisualMsgsCopy;
VisualMsgs_L linkVisualMsgsCopy;
VisualMsgs_L visualMsgsCopy;
VisualMsgs_L collisionVisualMsgsCopy;
JointMsgs_L jointMsgsCopy;
LinkMsgs_L linkMsgsCopy;
{
std::lock_guard<std::mutex> lock(*this->dataPtr->receiveMutex);
std::copy(this->dataPtr->sceneMsgs.begin(), this->dataPtr->sceneMsgs.end(),
std::back_inserter(sceneMsgsCopy));
this->dataPtr->sceneMsgs.clear();
std::copy(this->dataPtr->modelMsgs.begin(), this->dataPtr->modelMsgs.end(),
std::back_inserter(modelMsgsCopy));
this->dataPtr->modelMsgs.clear();
std::copy(this->dataPtr->sensorMsgs.begin(),
this->dataPtr->sensorMsgs.end(),
std::back_inserter(sensorMsgsCopy));
this->dataPtr->sensorMsgs.clear();
std::copy(this->dataPtr->lightFactoryMsgs.begin(),
this->dataPtr->lightFactoryMsgs.end(),
std::back_inserter(lightFactoryMsgsCopy));
this->dataPtr->lightFactoryMsgs.clear();
std::copy(this->dataPtr->lightModifyMsgs.begin(),
this->dataPtr->lightModifyMsgs.end(),
std::back_inserter(lightModifyMsgsCopy));
this->dataPtr->lightModifyMsgs.clear();
std::copy(this->dataPtr->modelVisualMsgs.begin(),
this->dataPtr->modelVisualMsgs.end(),
std::back_inserter(modelVisualMsgsCopy));
this->dataPtr->modelVisualMsgs.clear();
std::copy(this->dataPtr->linkVisualMsgs.begin(),
this->dataPtr->linkVisualMsgs.end(),
std::back_inserter(linkVisualMsgsCopy));
this->dataPtr->linkVisualMsgs.clear();
this->dataPtr->visualMsgs.sort(VisualMessageLessOp);
std::copy(this->dataPtr->visualMsgs.begin(),
this->dataPtr->visualMsgs.end(),
std::back_inserter(visualMsgsCopy));
this->dataPtr->visualMsgs.clear();
std::copy(this->dataPtr->collisionVisualMsgs.begin(),
this->dataPtr->collisionVisualMsgs.end(),
std::back_inserter(collisionVisualMsgsCopy));
this->dataPtr->collisionVisualMsgs.clear();
std::copy(this->dataPtr->jointMsgs.begin(), this->dataPtr->jointMsgs.end(),
std::back_inserter(jointMsgsCopy));
this->dataPtr->jointMsgs.clear();
std::copy(this->dataPtr->linkMsgs.begin(), this->dataPtr->linkMsgs.end(),
std::back_inserter(linkMsgsCopy));
this->dataPtr->linkMsgs.clear();
}
// Process the scene messages. DO THIS FIRST
for (sIter = sceneMsgsCopy.begin(); sIter != sceneMsgsCopy.end();)
{
if (this->ProcessSceneMsg(*sIter))
{
if (!this->dataPtr->initialized)
RTShaderSystem::Instance()->UpdateShaders();
this->dataPtr->initialized = true;
sceneMsgsCopy.erase(sIter++);
}
else
++sIter;
}
// Process the model messages.
for (modelIter = modelMsgsCopy.begin(); modelIter != modelMsgsCopy.end();)
{
if (this->ProcessModelMsg(**modelIter))
modelMsgsCopy.erase(modelIter++);
else
++modelIter;
}
// Process the sensor messages.
for (sensorIter = sensorMsgsCopy.begin(); sensorIter != sensorMsgsCopy.end();)
{
if (this->ProcessSensorMsg(*sensorIter))
sensorMsgsCopy.erase(sensorIter++);
else
++sensorIter;
}
// Process the light factory messages.
for (lightIter = lightFactoryMsgsCopy.begin();
lightIter != lightFactoryMsgsCopy.end();)
{
if (this->ProcessLightFactoryMsg(*lightIter))
lightFactoryMsgsCopy.erase(lightIter++);
else
++lightIter;
}
// Process the light modify messages.
for (lightIter = lightModifyMsgsCopy.begin();
lightIter != lightModifyMsgsCopy.end();)
{
if (this->ProcessLightModifyMsg(*lightIter))
lightModifyMsgsCopy.erase(lightIter++);
else
++lightIter;
}
// Process the model visual messages.
for (visualIter = modelVisualMsgsCopy.begin();
visualIter != modelVisualMsgsCopy.end();)
{
if (this->ProcessVisualMsg(*visualIter, Visual::VT_MODEL))
modelVisualMsgsCopy.erase(visualIter++);
else
++visualIter;
}
// Process the link visual messages.
for (visualIter = linkVisualMsgsCopy.begin();
visualIter != linkVisualMsgsCopy.end();)
{
if (this->ProcessVisualMsg(*visualIter, Visual::VT_LINK))
linkVisualMsgsCopy.erase(visualIter++);
else
++visualIter;
}
// Process the visual messages.
for (visualIter = visualMsgsCopy.begin(); visualIter != visualMsgsCopy.end();)
{
Visual::VisualType visualType = Visual::VT_VISUAL;
if ((*visualIter)->has_type())
visualType = Visual::ConvertVisualType((*visualIter)->type());
if (this->ProcessVisualMsg(*visualIter, visualType))
visualMsgsCopy.erase(visualIter++);
else
++visualIter;
}
// Process the collision visual messages.
for (visualIter = collisionVisualMsgsCopy.begin();
visualIter != collisionVisualMsgsCopy.end();)
{
if (this->ProcessVisualMsg(*visualIter, Visual::VT_COLLISION))
collisionVisualMsgsCopy.erase(visualIter++);
else
++visualIter;
}
// Process the joint messages.
for (jointIter = jointMsgsCopy.begin(); jointIter != jointMsgsCopy.end();)
{
if (this->ProcessJointMsg(*jointIter))
jointMsgsCopy.erase(jointIter++);
else
++jointIter;
}
// Process the link messages.
for (linkIter = linkMsgsCopy.begin(); linkIter != linkMsgsCopy.end();)
{
if (this->ProcessLinkMsg(*linkIter))
linkMsgsCopy.erase(linkIter++);
else
++linkIter;
}
// Process the request messages
for (rIter = this->dataPtr->requestMsgs.begin();
rIter != this->dataPtr->requestMsgs.end(); ++rIter)
{
this->ProcessRequestMsg(*rIter);
}
this->dataPtr->requestMsgs.clear();
{
std::lock_guard<std::mutex> lock(*this->dataPtr->receiveMutex);
std::copy(sceneMsgsCopy.begin(), sceneMsgsCopy.end(),
std::front_inserter(this->dataPtr->sceneMsgs));
std::copy(modelMsgsCopy.begin(), modelMsgsCopy.end(),
std::front_inserter(this->dataPtr->modelMsgs));
std::copy(sensorMsgsCopy.begin(), sensorMsgsCopy.end(),
std::front_inserter(this->dataPtr->sensorMsgs));
std::copy(lightFactoryMsgsCopy.begin(), lightFactoryMsgsCopy.end(),
std::front_inserter(this->dataPtr->lightFactoryMsgs));
std::copy(lightModifyMsgsCopy.begin(), lightModifyMsgsCopy.end(),
std::front_inserter(this->dataPtr->lightModifyMsgs));
std::copy(modelVisualMsgsCopy.begin(), modelVisualMsgsCopy.end(),
std::front_inserter(this->dataPtr->modelVisualMsgs));
std::copy(linkVisualMsgsCopy.begin(), linkVisualMsgsCopy.end(),
std::front_inserter(this->dataPtr->linkVisualMsgs));
std::copy(visualMsgsCopy.begin(), visualMsgsCopy.end(),
std::front_inserter(this->dataPtr->visualMsgs));
std::copy(collisionVisualMsgsCopy.begin(), collisionVisualMsgsCopy.end(),
std::front_inserter(this->dataPtr->collisionVisualMsgs));
std::copy(jointMsgsCopy.begin(), jointMsgsCopy.end(),
std::front_inserter(this->dataPtr->jointMsgs));
std::copy(linkMsgsCopy.begin(), linkMsgsCopy.end(),
std::front_inserter(this->dataPtr->linkMsgs));
}
// update the rt shader
RTShaderSystem::Instance()->Update();
{
std::lock_guard<std::recursive_mutex> lock(this->dataPtr->poseMsgMutex);
// Process all the model messages last. Remove pose message from the list
// only when a corresponding visual exits. We may receive pose updates
// over the wire before we recieve the visual
pIter = this->dataPtr->poseMsgs.begin();
while (pIter != this->dataPtr->poseMsgs.end())
{
Visual_M::iterator iter = this->dataPtr->visuals.find(pIter->first);
if (iter != this->dataPtr->visuals.end() && iter->second)
{
// If an object is selected, don't let the physics engine move it.
if (!this->dataPtr->selectedVis
|| this->dataPtr->selectionMode != "move" ||
(iter->first != this->dataPtr->selectedVis->GetId() &&
!this->dataPtr->selectedVis->IsAncestorOf(iter->second)))
{
ignition::math::Pose3d pose = msgs::ConvertIgn(pIter->second);
GZ_ASSERT(iter->second, "Visual pointer is NULL");
iter->second->SetPose(pose);
PoseMsgs_M::iterator prev = pIter++;
this->dataPtr->poseMsgs.erase(prev);
}
else
++pIter;
}
else
++pIter;
}
// process light pose messages
auto lpIter = this->dataPtr->lightPoseMsgs.begin();
while (lpIter != this->dataPtr->lightPoseMsgs.end())
{
auto lIter = this->dataPtr->lights.find(lpIter->first);
if (lIter != this->dataPtr->lights.end())
{
ignition::math::Pose3d pose = msgs::ConvertIgn(lpIter->second);
lIter->second->SetPosition(pose.Pos());
lIter->second->SetRotation(pose.Rot());
auto prev = lpIter++;
this->dataPtr->lightPoseMsgs.erase(prev);
}
else
lpIter++;
}
// process skeleton pose msgs
spIter = this->dataPtr->skeletonPoseMsgs.begin();
while (spIter != this->dataPtr->skeletonPoseMsgs.end())
{
Visual_M::iterator iter =
this->dataPtr->visuals.find((*spIter)->model_id());
for (int i = 0; i < (*spIter)->pose_size(); ++i)
{
const msgs::Pose& pose_msg = (*spIter)->pose(i);
if (pose_msg.has_id())
{
Visual_M::iterator iter2 = this->dataPtr->visuals.find(pose_msg.id());
if (iter2 != this->dataPtr->visuals.end())
{
// If an object is selected, don't let the physics engine move it.
if (!this->dataPtr->selectedVis ||
this->dataPtr->selectionMode != "move" ||
(iter->first != this->dataPtr->selectedVis->GetId()&&
!this->dataPtr->selectedVis->IsAncestorOf(iter->second)))
{
ignition::math::Pose3d pose = msgs::ConvertIgn(pose_msg);
iter2->second->SetPose(pose);
}
}
}
}
if (iter != this->dataPtr->visuals.end())
{
iter->second->SetSkeletonPose(*(*spIter).get());
SkeletonPoseMsgs_L::iterator prev = spIter++;
this->dataPtr->skeletonPoseMsgs.erase(prev);
}
else
++spIter;
}
// official time stamp of approval
this->dataPtr->sceneSimTimePosesApplied =
this->dataPtr->sceneSimTimePosesReceived;
}
}
/////////////////////////////////////////////////
void Scene::OnJointMsg(ConstJointPtr &_msg)
{
std::lock_guard<std::mutex> lock(*this->dataPtr->receiveMutex);
this->dataPtr->jointMsgs.push_back(_msg);
}
/////////////////////////////////////////////////
bool Scene::ProcessSensorMsg(ConstSensorPtr &_msg)
{
if (!this->dataPtr->enableVisualizations)
return true;
if ((_msg->type() == "ray" || _msg->type() == "gpu_ray") && _msg->visualize()
&& !_msg->topic().empty())
{
std::string rayVisualName = _msg->parent() + "::" + _msg->name();
if (this->dataPtr->visuals.find(_msg->id()) == this->dataPtr->visuals.end())
{
VisualPtr parentVis = this->GetVisual(_msg->parent_id());
if (!parentVis)
return false;
LaserVisualPtr laserVis(new LaserVisual(
rayVisualName+"_GUIONLY_laser_vis", parentVis, _msg->topic()));
laserVis->Load();
laserVis->SetId(_msg->id());
this->dataPtr->visuals[_msg->id()] = laserVis;
}
}
else if ((_msg->type() == "sonar") && _msg->visualize()
&& !_msg->topic().empty())
{
std::string sonarVisualName = _msg->parent() + "::" + _msg->name();
if (this->dataPtr->visuals.find(_msg->id()) == this->dataPtr->visuals.end())
{
VisualPtr parentVis = this->GetVisual(_msg->parent());
if (!parentVis)
return false;
SonarVisualPtr sonarVis(new SonarVisual(
sonarVisualName+"_GUIONLY_sonar_vis", parentVis, _msg->topic()));
sonarVis->Load();
sonarVis->SetId(_msg->id());
this->dataPtr->visuals[_msg->id()] = sonarVis;
}
}
else if ((_msg->type() == "force_torque") && _msg->visualize()
&& !_msg->topic().empty())
{
std::string wrenchVisualName = _msg->parent() + "::" + _msg->name();
if (this->dataPtr->visuals.find(_msg->id()) == this->dataPtr->visuals.end())
{
if (this->dataPtr->joints.find(_msg->parent()) ==
this->dataPtr->joints.end())
{
return false;
}
ConstJointPtr jointMsg = this->dataPtr->joints[_msg->parent()];
if (!jointMsg)
return false;
VisualPtr parentVis = this->GetVisual(jointMsg->child());
if (!parentVis)
return false;
WrenchVisualPtr wrenchVis(new WrenchVisual(
wrenchVisualName+"_GUIONLY_wrench_vis", parentVis,
_msg->topic()));
wrenchVis->Load(jointMsg);
wrenchVis->SetId(_msg->id());
this->dataPtr->visuals[_msg->id()] = wrenchVis;
}
}
else if (_msg->type() == "camera" && _msg->visualize())
{
VisualPtr parentVis = this->GetVisual(_msg->parent_id());
if (!parentVis)
return false;
// image size is 0 if rendering is unavailable
if (_msg->camera().image_size().x() > 0 &&
_msg->camera().image_size().y() > 0)
{
Visual_M::iterator iter = this->dataPtr->visuals.find(_msg->id());
if (iter == this->dataPtr->visuals.end())
{
CameraVisualPtr cameraVis(new CameraVisual(
_msg->name()+"_GUIONLY_camera_vis", parentVis));
// need to call AttachVisual in order for cameraVis to be added to
// parentVis' children list so that it can be properly deleted.
parentVis->AttachVisual(cameraVis);
cameraVis->SetPose(msgs::ConvertIgn(_msg->pose()));
cameraVis->SetId(_msg->id());
cameraVis->Load(_msg->camera());
this->dataPtr->visuals[cameraVis->GetId()] = cameraVis;
}
}
}
else if (_msg->type() == "logical_camera" && _msg->visualize())
{
VisualPtr parentVis = this->GetVisual(_msg->parent_id());
if (!parentVis)
return false;
Visual_M::iterator iter = this->dataPtr->visuals.find(_msg->id());
if (iter == this->dataPtr->visuals.end())
{
LogicalCameraVisualPtr cameraVis(new LogicalCameraVisual(
_msg->name()+"_GUIONLY_logical_camera_vis", parentVis));
// need to call AttachVisual in order for cameraVis to be added to
// parentVis' children list so that it can be properly deleted.
parentVis->AttachVisual(cameraVis);
cameraVis->SetPose(msgs::ConvertIgn(_msg->pose()));
cameraVis->SetId(_msg->id());
cameraVis->Load(_msg->logical_camera());
this->dataPtr->visuals[cameraVis->GetId()] = cameraVis;
}
else if (_msg->has_pose())
{
iter->second->SetPose(msgs::ConvertIgn(_msg->pose()));
}
}
else if (_msg->type() == "contact" && _msg->visualize() &&
!_msg->topic().empty())
{
ContactVisualPtr contactVis(new ContactVisual(
_msg->name()+"__GUIONLY_CONTACT_VISUAL__",
this->dataPtr->worldVisual, _msg->topic()));
contactVis->SetId(_msg->id());
this->dataPtr->contactVisId = _msg->id();
this->dataPtr->visuals[contactVis->GetId()] = contactVis;
}
else if (_msg->type() == "rfidtag" && _msg->visualize() &&
!_msg->topic().empty())
{
VisualPtr parentVis = this->GetVisual(_msg->parent());
if (!parentVis)
return false;
RFIDTagVisualPtr rfidVis(new RFIDTagVisual(
_msg->name() + "_GUIONLY_rfidtag_vis", parentVis, _msg->topic()));
rfidVis->SetId(_msg->id());
this->dataPtr->visuals[rfidVis->GetId()] = rfidVis;
}
else if (_msg->type() == "rfid" && _msg->visualize() &&
!_msg->topic().empty())
{
VisualPtr parentVis = this->GetVisual(_msg->parent());
if (!parentVis)
return false;
RFIDVisualPtr rfidVis(new RFIDVisual(
_msg->name() + "_GUIONLY_rfid_vis", parentVis, _msg->topic()));
rfidVis->SetId(_msg->id());
this->dataPtr->visuals[rfidVis->GetId()] = rfidVis;
}
else if (_msg->type() == "wireless_transmitter" && _msg->visualize() &&
!_msg->topic().empty())
{
VisualPtr parentVis = this->GetVisual(_msg->parent());
if (!parentVis)
return false;
VisualPtr transmitterVis(new TransmitterVisual(
_msg->name() + "_GUIONLY_transmitter_vis", parentVis, _msg->topic()));
this->dataPtr->visuals[transmitterVis->GetId()] = transmitterVis;
transmitterVis->Load();
}
return true;
}
/////////////////////////////////////////////////
bool Scene::ProcessLinkMsg(ConstLinkPtr &_msg)
{
VisualPtr linkVis;
if (_msg->has_id())
linkVis = this->GetVisual(_msg->id());
else
linkVis = this->GetVisual(_msg->name());
if (!linkVis)
{
gzerr << "No link visual with id[" << _msg->id() << "] and name["
<< _msg->name() << "]\n";
return false;
}
for (int i = 0; i < _msg->projector_size(); ++i)
{
std::string pname = _msg->name() + "::" + _msg->projector(i).name();
if (this->dataPtr->projectors.find(pname) ==
this->dataPtr->projectors.end())
{
Projector *projector = new Projector(linkVis);
projector->Load(_msg->projector(i));
projector->Toggle();
this->dataPtr->projectors[pname] = projector;
}
}
linkVis->SetTypeMsg(&*_msg);
// Trigger visualizations that depend on type msg
linkVis->ShowInertia(this->dataPtr->showInertias);
linkVis->ShowCOM(this->dataPtr->showCOMs);
linkVis->ShowLinkFrame(this->dataPtr->showLinkFrames);
linkVis->ShowCollision(this->dataPtr->showCollisions);
linkVis->ShowJoints(this->dataPtr->showJoints);
return true;
}
/////////////////////////////////////////////////
bool Scene::ProcessJointMsg(ConstJointPtr &_msg)
{
VisualPtr childVis;
if (_msg->has_child() && _msg->child() == "world")
childVis = this->dataPtr->worldVisual;
else if (_msg->has_child_id())
childVis = this->GetVisual(_msg->child_id());
if (!childVis)
return false;
childVis->AddPendingChild(std::make_pair(Visual::VT_PHYSICS, &*_msg));
// If this needs to be added, make sure it is called after all of the visuals
// the childVis link have been loaded
// childVis->ShowJoints(this->dataPtr->showJoints);
ConstJointPtr msgCopy(_msg);
this->dataPtr->joints[_msg->name()] = msgCopy;
return true;
}
/////////////////////////////////////////////////
void Scene::OnScene(ConstScenePtr &_msg)
{
std::lock_guard<std::mutex> lock(*this->dataPtr->receiveMutex);
this->dataPtr->sceneMsgs.push_back(_msg);
}
/////////////////////////////////////////////////
void Scene::OnResponse(ConstResponsePtr &_msg)
{
if (!this->dataPtr->requestMsg ||
_msg->id() != this->dataPtr->requestMsg->id())
return;
msgs::Scene sceneMsg;
sceneMsg.ParseFromString(_msg->serialized_data());
boost::shared_ptr<msgs::Scene> sm(new msgs::Scene(sceneMsg));
std::lock_guard<std::mutex> lock(*this->dataPtr->receiveMutex);
this->dataPtr->sceneMsgs.push_back(sm);
this->dataPtr->requestMsg = NULL;
}
/////////////////////////////////////////////////
void Scene::OnRequest(ConstRequestPtr &_msg)
{
std::lock_guard<std::mutex> lock(*this->dataPtr->receiveMutex);
this->dataPtr->requestMsgs.push_back(_msg);
}
/////////////////////////////////////////////////
void Scene::ProcessRequestMsg(ConstRequestPtr &_msg)
{
if (_msg->request() == "entity_info")
{
msgs::Response response;
response.set_id(_msg->id());
response.set_request(_msg->request());
Light_M::iterator iter;
iter = this->dataPtr->lights.find(_msg->data());
if (iter != this->dataPtr->lights.end())
{
msgs::Light lightMsg;
iter->second->FillMsg(lightMsg);
std::string *serializedData = response.mutable_serialized_data();
lightMsg.SerializeToString(serializedData);
response.set_type(lightMsg.GetTypeName());
response.set_response("success");
}
else
response.set_response("failure");
// this->responsePub->Publish(response);
}
else if (_msg->request() == "entity_delete")
{
Light_M::iterator lightIter = this->dataPtr->lights.find(_msg->data());
// Check to see if the deleted entity is a light.
if (lightIter != this->dataPtr->lights.end())
{
this->dataPtr->lights.erase(lightIter);
}
// Otherwise delete a visual
else
{
VisualPtr visPtr;
try
{
auto iter = this->dataPtr->visuals.find(
boost::lexical_cast<uint32_t>(_msg->data()));
if (iter != this->dataPtr->visuals.end())
visPtr = iter->second;
} catch(...)
{
visPtr = this->GetVisual(_msg->data());
}
if (visPtr)
this->RemoveVisual(visPtr);
}
}
else if (_msg->request() == "show_contact")
{
this->ShowContacts(true);
}
else if (_msg->request() == "hide_contact")
{
this->ShowContacts(false);
}
else if (_msg->request() == "show_collision")
{
if (_msg->data() == "all")
this->ShowCollisions(true);
else
{
VisualPtr vis = this->GetVisual(_msg->data());
if (vis)
vis->ShowCollision(true);
else
gzerr << "Unable to find visual[" << _msg->data() << "]\n";
}
}
else if (_msg->request() == "hide_collision")
{
if (_msg->data() == "all")
this->ShowCollisions(false);
else
{
VisualPtr vis = this->GetVisual(_msg->data());
if (vis)
vis->ShowCollision(false);
}
}
else if (_msg->request() == "show_joints")
{
if (_msg->data() == "all")
this->ShowJoints(true);
else
{
VisualPtr vis = this->GetVisual(_msg->data());
if (vis)
vis->ShowJoints(true);
else
gzerr << "Unable to find joint visual[" << _msg->data() << "]\n";
}
}
else if (_msg->request() == "hide_joints")
{
if (_msg->data() == "all")
this->ShowJoints(false);
else
{
VisualPtr vis = this->GetVisual(_msg->data());
if (vis)
vis->ShowJoints(false);
}
}
else if (_msg->request() == "show_com")
{
if (_msg->data() == "all")
this->ShowCOMs(true);
else
{
VisualPtr vis = this->GetVisual(_msg->data());
if (vis)
vis->ShowCOM(true);
else
gzerr << "Unable to find COM visual[" << _msg->data() << "]\n";
}
}
else if (_msg->request() == "hide_com")
{
if (_msg->data() == "all")
this->ShowCOMs(false);
else
{
VisualPtr vis = this->GetVisual(_msg->data());
if (vis)
vis->ShowCOM(false);
}
}
else if (_msg->request() == "show_inertia")
{
if (_msg->data() == "all")
this->ShowInertias(true);
else
{
VisualPtr vis = this->GetVisual(_msg->data());
if (vis)
vis->ShowInertia(true);
else
gzerr << "Unable to find inertia visual[" << _msg->data() << "]\n";
}
}
else if (_msg->request() == "hide_inertia")
{
if (_msg->data() == "all")
this->ShowInertias(false);
else
{
VisualPtr vis = this->GetVisual(_msg->data());
if (vis)
vis->ShowInertia(false);
}
}
else if (_msg->request() == "show_link_frame")
{
if (_msg->data() == "all")
this->ShowLinkFrames(true);
else
{
VisualPtr vis = this->GetVisual(_msg->data());
if (vis)
vis->ShowLinkFrame(true);
else
gzerr << "Unable to find link frame visual[" << _msg->data() << "]\n";
}
}
else if (_msg->request() == "hide_link_frame")
{
if (_msg->data() == "all")
this->ShowLinkFrames(false);
else
{
VisualPtr vis = this->GetVisual(_msg->data());
if (vis)
vis->ShowLinkFrame(false);
}
}
else if (_msg->request() == "set_transparent")
{
if (_msg->data() == "all")
this->SetTransparent(true);
else
{
VisualPtr vis = this->GetVisual(_msg->data());
if (vis)
vis->SetTransparency(0.5);
}
}
else if (_msg->request() == "set_wireframe")
{
if (_msg->data() == "all")
this->SetWireframe(true);
else
{
VisualPtr vis = this->GetVisual(_msg->data());
if (vis)
vis->SetWireframe(true);
}
}
else if (_msg->request() == "set_solid")
{
if (_msg->data() == "all")
this->SetWireframe(false);
else
{
VisualPtr vis = this->GetVisual(_msg->data());
if (vis)
vis->SetWireframe(false);
}
}
else if (_msg->request() == "set_opaque")
{
if (_msg->data() == "all")
this->SetTransparent(false);
else
{
VisualPtr vis = this->GetVisual(_msg->data());
if (vis)
vis->SetTransparency(0.0);
}
}
else if (_msg->request() == "show_skeleton")
{
VisualPtr vis = this->GetVisual(_msg->data());
bool show = (math::equal(_msg->dbl_data(), 1.0)) ? true : false;
if (vis)
vis->ShowSkeleton(show);
}
}
/////////////////////////////////////////////////
bool Scene::ProcessVisualMsg(ConstVisualPtr &_msg, Visual::VisualType _type)
{
Visual_M::iterator iter = this->dataPtr->visuals.end();
if (_msg->has_id())
iter = this->dataPtr->visuals.find(_msg->id());
else
{
VisualPtr vis = this->GetVisual(_msg->name());
iter = vis ? this->dataPtr->visuals.find(vis->GetId()) :
this->dataPtr->visuals.end();
}
// Deleting a visual
if (_msg->has_delete_me() && _msg->delete_me())
{
if (iter != this->dataPtr->visuals.end())
{
this->dataPtr->visuals.erase(iter);
return true;
}
else
return false;
}
// Updating existing visual
if (iter != this->dataPtr->visuals.end())
{
iter->second->UpdateFromMsg(_msg);
return true;
}
// Creating heightmap
// FIXME: A bit of a hack.
if (_msg->has_geometry() &&
_msg->geometry().type() == msgs::Geometry::HEIGHTMAP &&
_type != Visual::VT_COLLISION)
{
if (this->dataPtr->terrain)
{
// Only one Heightmap can be created per Scene
return true;
}
else
{
if (!this->dataPtr->terrain)
{
// create a dummy visual for loading heightmap visual plugin
// TODO make heightmap a visual to avoid special treatment here?
VisualPtr visual(new Visual(_msg->name(), this->dataPtr->worldVisual));
auto m = *_msg.get();
m.clear_material();
visual->Load(msgs::VisualToSDF(m));
this->dataPtr->terrain = new Heightmap(shared_from_this());
// check the material fields and set material if it is specified
if (_msg->has_material())
{
auto matMsg = _msg->material();
if (matMsg.has_script())
{
auto scriptMsg = matMsg.script();
for (auto const uri : scriptMsg.uri())
{
if (!uri.empty())
RenderEngine::Instance()->AddResourcePath(uri);
}
std::string matName = scriptMsg.name();
this->dataPtr->terrain->SetMaterial(matName);
}
}
this->dataPtr->terrain->SetLOD(this->dataPtr->heightmapLOD);
const double skirtLen = this->dataPtr->heightmapSkirtLength;
this->dataPtr->terrain->SetSkirtLength(skirtLen);
this->dataPtr->terrain->LoadFromMsg(_msg);
}
}
return true;
}
// Creating collision
if (_type == Visual::VT_COLLISION)
{
// Collisions need a parent
if (!_msg->has_parent_name() && !_msg->has_parent_id())
{
gzerr << "Missing parent for collision visual [" << _msg->name() << "]"
<< std::endl;
return false;
}
// Make sure the parent visual exists before trying to add a child visual
auto parent = this->dataPtr->visuals.find(_msg->parent_id());
if (parent == this->dataPtr->visuals.end())
{
return false;
}
parent->second->AddPendingChild(std::make_pair(_type, &*_msg));
parent->second->ShowCollision(this->dataPtr->showCollisions);
return true;
}
// All other visuals
VisualPtr visual;
// If the visual has a parent which is not the name of the scene...
if (_msg->has_parent_name() && _msg->parent_name() != this->Name())
{
// Make sure the parent visual exists before trying to add a child
// visual
VisualPtr parent = this->GetVisual(_msg->parent_name());
if (!parent)
return false;
visual.reset(new Visual(_msg->name(), parent));
}
else
{
// Make sure the world visual exists before trying to add a child visual
if (!this->dataPtr->worldVisual)
return false;
// Add a visual that is attached to the scene root
visual.reset(new Visual(_msg->name(), this->dataPtr->worldVisual));
}
if (_msg->has_id())
visual->SetId(_msg->id());
visual->LoadFromMsg(_msg);
visual->SetType(_type);
this->dataPtr->visuals[visual->GetId()] = visual;
if (visual->GetName().find("__SKELETON_VISUAL__") != std::string::npos)
{
visual->SetVisible(false);
visual->SetVisibilityFlags(GZ_VISIBILITY_GUI);
}
if (visual->GetType() == Visual::VT_MODEL)
visual->SetTransparency(this->dataPtr->transparent ? 0.5 : 0.0);
visual->SetWireframe(this->dataPtr->wireframe);
return true;
}
/////////////////////////////////////////////////
common::Time Scene::GetSimTime() const
{
return this->SimTime();
}
/////////////////////////////////////////////////
common::Time Scene::SimTime() const
{
std::lock_guard<std::mutex> lock(*this->dataPtr->receiveMutex);
return this->dataPtr->sceneSimTimePosesApplied;
}
/////////////////////////////////////////////////
void Scene::OnPoseMsg(ConstPosesStampedPtr &_msg)
{
std::lock_guard<std::recursive_mutex> lock(this->dataPtr->poseMsgMutex);
this->dataPtr->sceneSimTimePosesReceived =
common::Time(_msg->time().sec(), _msg->time().nsec());
for (int i = 0; i < _msg->pose_size(); ++i)
{
auto p = _msg->pose(i);
/// TODO: empty id used to indicate it's pose of a light
/// remove this check once light.proto has an id field
if (p.has_id())
{
PoseMsgs_M::iterator iter =
this->dataPtr->poseMsgs.find(p.id());
if (iter != this->dataPtr->poseMsgs.end())
iter->second.CopyFrom(p);
else
this->dataPtr->poseMsgs.insert(std::make_pair(p.id(), p));
}
else
{
auto iter = this->dataPtr->lightPoseMsgs.find(p.name());
if (iter != this->dataPtr->lightPoseMsgs.end())
iter->second.CopyFrom(p);
else
this->dataPtr->lightPoseMsgs.insert(std::make_pair(p.name(), p));
}
}
}
/////////////////////////////////////////////////
void Scene::OnSkeletonPoseMsg(ConstPoseAnimationPtr &_msg)
{
std::lock_guard<std::mutex> lock(*this->dataPtr->receiveMutex);
SkeletonPoseMsgs_L::iterator iter;
// Find an old model message, and remove them
for (iter = this->dataPtr->skeletonPoseMsgs.begin();
iter != this->dataPtr->skeletonPoseMsgs.end(); ++iter)
{
if ((*iter)->model_name() == _msg->model_name())
{
this->dataPtr->skeletonPoseMsgs.erase(iter);
break;
}
}
this->dataPtr->skeletonPoseMsgs.push_back(_msg);
}
/////////////////////////////////////////////////
void Scene::OnLightFactoryMsg(ConstLightPtr &_msg)
{
std::lock_guard<std::mutex> lock(*this->dataPtr->receiveMutex);
this->dataPtr->lightFactoryMsgs.push_back(_msg);
}
/////////////////////////////////////////////////
void Scene::OnLightModifyMsg(ConstLightPtr &_msg)
{
std::lock_guard<std::mutex> lock(*this->dataPtr->receiveMutex);
this->dataPtr->lightModifyMsgs.push_back(_msg);
}
/////////////////////////////////////////////////
bool Scene::ProcessLightFactoryMsg(ConstLightPtr &_msg)
{
Light_M::iterator iter;
iter = this->dataPtr->lights.find(_msg->name());
if (iter == this->dataPtr->lights.end())
{
LightPtr light(new Light(shared_from_this()));
light->LoadFromMsg(_msg);
this->dataPtr->lights[_msg->name()] = light;
RTShaderSystem::Instance()->UpdateShaders();
}
else
{
gzerr << "Light [" << _msg->name() << "] already exists."
<< " Use topic ~/light/modify to modify it." << std::endl;
// we don't want to return false because it keeps the msg in the
// list and causes it to be processed again and again.
}
return true;
}
/////////////////////////////////////////////////
bool Scene::ProcessLightModifyMsg(ConstLightPtr &_msg)
{
Light_M::iterator iter;
iter = this->dataPtr->lights.find(_msg->name());
if (iter == this->dataPtr->lights.end())
{
// commented out for now as sometimes physics light messages could arrive
// before the rendering light is created, e.g. light pose updates.
// See issue #1778
// gzerr << "Light [" << _msg->name() << "] not found."
// << " Use topic ~/factory/light to spawn a new light." << std::endl;
return false;
}
else
{
iter->second->UpdateFromMsg(_msg);
RTShaderSystem::Instance()->UpdateShaders();
}
return true;
}
/////////////////////////////////////////////////
void Scene::OnModelMsg(ConstModelPtr &_msg)
{
std::lock_guard<std::mutex> lock(*this->dataPtr->receiveMutex);
this->dataPtr->modelMsgs.push_back(_msg);
}
/////////////////////////////////////////////////
void Scene::OnSkyMsg(ConstSkyPtr &_msg)
{
if (!this->dataPtr->skyx)
return;
Ogre::Root::getSingletonPtr()->addFrameListener(this->dataPtr->skyx);
this->dataPtr->skyx->update(0);
this->dataPtr->skyx->setVisible(true);
SkyX::VClouds::VClouds *vclouds =
this->dataPtr->skyx->getVCloudsManager()->getVClouds();
if (_msg->has_time())
{
Ogre::Vector3 t = this->dataPtr->skyxController->getTime();
t.x = math::clamp(_msg->time(), 0.0, 24.0);
this->dataPtr->skyxController->setTime(t);
}
if (_msg->has_sunrise())
{
Ogre::Vector3 t = this->dataPtr->skyxController->getTime();
t.y = math::clamp(_msg->sunrise(), 0.0, 24.0);
this->dataPtr->skyxController->setTime(t);
}
if (_msg->has_sunset())
{
Ogre::Vector3 t = this->dataPtr->skyxController->getTime();
t.z = math::clamp(_msg->sunset(), 0.0, 24.0);
this->dataPtr->skyxController->setTime(t);
}
if (_msg->has_wind_speed())
vclouds->setWindSpeed(_msg->wind_speed());
if (_msg->has_wind_direction())
vclouds->setWindDirection(Ogre::Radian(_msg->wind_direction()));
if (_msg->has_cloud_ambient())
{
vclouds->setAmbientFactors(Ogre::Vector4(
_msg->cloud_ambient().r(),
_msg->cloud_ambient().g(),
_msg->cloud_ambient().b(),
_msg->cloud_ambient().a()));
}
if (_msg->has_humidity())
{
Ogre::Vector2 wheater = vclouds->getWheater();
vclouds->setWheater(math::clamp(_msg->humidity(), 0.0, 1.0),
wheater.y, true);
}
if (_msg->has_mean_cloud_size())
{
Ogre::Vector2 wheater = vclouds->getWheater();
vclouds->setWheater(wheater.x,
math::clamp(_msg->mean_cloud_size(), 0.0, 1.0), true);
}
this->dataPtr->skyx->update(0);
}
/////////////////////////////////////////////////
void Scene::SetSky()
{
// Create SkyX
this->dataPtr->skyxController = new SkyX::BasicController();
this->dataPtr->skyx = new SkyX::SkyX(this->dataPtr->manager,
this->dataPtr->skyxController);
this->dataPtr->skyx->create();
this->dataPtr->skyx->setTimeMultiplier(0);
// Set the time: x = current time[0-24], y = sunrise time[0-24],
// z = sunset time[0-24]
this->dataPtr->skyxController->setTime(Ogre::Vector3(10.0, 6.0, 20.0f));
// Moon phase in [-1,1] range, where -1 means fully covered Moon,
// 0 clear Moon and 1 fully covered Moon
this->dataPtr->skyxController->setMoonPhase(0);
this->dataPtr->skyx->getAtmosphereManager()->setOptions(
SkyX::AtmosphereManager::Options(
9.77501f, // Inner radius
10.2963f, // Outer radius
0.01f, // Height position
0.0017f, // RayleighMultiplier
0.000675f, // MieMultiplier
30, // Sun Intensity
Ogre::Vector3(0.57f, 0.54f, 0.44f), // Wavelength
-0.991f, 2.5f, 4));
this->dataPtr->skyx->getVCloudsManager()->setWindSpeed(0.6);
// Use true to update volumetric clouds based on the time multiplier
this->dataPtr->skyx->getVCloudsManager()->setAutoupdate(false);
SkyX::VClouds::VClouds *vclouds =
this->dataPtr->skyx->getVCloudsManager()->getVClouds();
// Set wind direction in radians
vclouds->setWindDirection(Ogre::Radian(0.0));
vclouds->setAmbientColor(Ogre::Vector3(0.9, 0.9, 1.0));
// x = sun light power
// y = sun beta multiplier
// z = ambient color multiplier
// w = distance attenuation
vclouds->setLightResponse(Ogre::Vector4(0.9, 0.6, 0.5, 0.3));
vclouds->setAmbientFactors(Ogre::Vector4(0.45, 0.3, 0.6, 0.1));
vclouds->setWheater(.6, .6, false);
if (true)
{
// Create VClouds
if (!this->dataPtr->skyx->getVCloudsManager()->isCreated())
{
// SkyX::MeshManager::getSkydomeRadius(...) works for both finite and
// infinite(=0) camera far clip distances
this->dataPtr->skyx->getVCloudsManager()->create(2000.0);
// this->dataPtr->skyx->getMeshManager()->getSkydomeRadius(
// mRenderingCamera));
}
}
else
{
// Remove VClouds
if (this->dataPtr->skyx->getVCloudsManager()->isCreated())
{
this->dataPtr->skyx->getVCloudsManager()->remove();
}
}
// vclouds->getLightningManager()->setEnabled(preset.vcLightnings);
// vclouds->getLightningManager()->setAverageLightningApparitionTime(
// preset.vcLightningsAT);
// vclouds->getLightningManager()->setLightningColor(
// preset.vcLightningsColor);
// vclouds->getLightningManager()->setLightningTimeMultiplier(
// preset.vcLightningsTM);
this->dataPtr->skyx->setVisible(false);
}
/////////////////////////////////////////////////
void Scene::SetShadowsEnabled(bool _value)
{
// If a usercamera is set to stereo mode, then turn off shadows.
// If a usercamera uses orthographic projection, then turn off shadows.
// Our shadow mapping technique disables stereo.
bool shadowOverride = true;
for (std::vector<UserCameraPtr>::iterator iter =
this->dataPtr->userCameras.begin();
iter != this->dataPtr->userCameras.end() && shadowOverride; ++iter)
{
shadowOverride = !(*iter)->StereoEnabled() &&
(*iter)->ProjectionType() != "orthographic";
}
_value = _value && shadowOverride;
this->dataPtr->sdf->GetElement("shadows")->Set(_value);
if (RenderEngine::Instance()->GetRenderPathType() == RenderEngine::DEFERRED)
{
#if OGRE_VERSION_MAJOR >= 1 && OGRE_VERSION_MINOR >= 8
this->dataPtr->manager->setShadowTechnique(
Ogre::SHADOWTYPE_TEXTURE_ADDITIVE);
this->dataPtr->manager->setShadowTextureCasterMaterial(
"DeferredRendering/Shadows/RSMCaster_Spot");
this->dataPtr->manager->setShadowTextureCount(1);
this->dataPtr->manager->setShadowFarDistance(150);
// Use a value of "2" to use a different depth buffer pool and
// avoid sharing this with the Backbuffer's
this->dataPtr->manager->setShadowTextureConfig(0,
this->dataPtr->shadowTextureSize, this->dataPtr->shadowTextureSize,
Ogre::PF_FLOAT32_RGBA, 0, 2);
this->dataPtr->manager->setShadowDirectionalLightExtrusionDistance(75);
this->dataPtr->manager->setShadowCasterRenderBackFaces(false);
this->dataPtr->manager->setShadowTextureSelfShadow(true);
this->dataPtr->manager->setShadowDirLightTextureOffset(1.75);
#endif
}
else if (RenderEngine::Instance()->GetRenderPathType() ==
RenderEngine::FORWARD)
{
// RT Shader shadows
if (_value)
RTShaderSystem::Instance()->ApplyShadows(shared_from_this());
else
RTShaderSystem::Instance()->RemoveShadows(shared_from_this());
}
else
{
this->dataPtr->manager->setShadowCasterRenderBackFaces(false);
this->dataPtr->manager->setShadowTextureSize(
this->dataPtr->shadowTextureSize);
// The default shadows.
if (_value && this->dataPtr->manager->getShadowTechnique()
!= Ogre::SHADOWTYPE_TEXTURE_ADDITIVE)
{
this->dataPtr->manager->setShadowTechnique(
Ogre::SHADOWTYPE_TEXTURE_ADDITIVE);
}
else
this->dataPtr->manager->setShadowTechnique(Ogre::SHADOWTYPE_NONE);
}
}
/////////////////////////////////////////////////
bool Scene::GetShadowsEnabled() const
{
return ShadowsEnabled();
}
/////////////////////////////////////////////////
bool Scene::ShadowsEnabled() const
{
return this->dataPtr->sdf->Get<bool>("shadows");
}
/////////////////////////////////////////////////
bool Scene::SetShadowTextureSize(const unsigned int _size)
{
// check if texture size is a power of 2
if (!ignition::math::isPowerOfTwo(_size))
{
gzerr << "Shadow texture size must be a power of 2" << std::endl;
return false;
}
this->dataPtr->shadowTextureSize = _size;
if (RenderEngine::Instance()->GetRenderPathType() ==
RenderEngine::FORWARD)
{
// RT Shader shadows
if (!RTShaderSystem::Instance()->SetShadowTextureSize(_size))
return false;
if (this->ShadowsEnabled())
{
// re-enable the shadows to take effect
this->SetShadowsEnabled(false);
this->SetShadowsEnabled(true);
}
}
else
{
this->dataPtr->manager->setShadowTextureSize(
this->dataPtr->shadowTextureSize);
}
return true;
}
/////////////////////////////////////////////////
unsigned int Scene::ShadowTextureSize() const
{
if (RenderEngine::Instance()->GetRenderPathType() ==
RenderEngine::FORWARD)
return RTShaderSystem::Instance()->ShadowTextureSize();
else
return this->dataPtr->shadowTextureSize;
}
/////////////////////////////////////////////////
void Scene::AddVisual(VisualPtr _vis)
{
if (this->dataPtr->visuals.find(_vis->GetId()) !=
this->dataPtr->visuals.end())
{
gzwarn << "Duplicate visuals detected[" << _vis->GetName() << "]\n";
}
this->dataPtr->visuals[_vis->GetId()] = _vis;
}
/////////////////////////////////////////////////
void Scene::RemoveVisual(uint32_t _id)
{
// Delete the visual
auto iter = this->dataPtr->visuals.find(_id);
if (iter != this->dataPtr->visuals.end())
{
VisualPtr vis = iter->second;
// Remove all projectors attached to the visual
auto piter = this->dataPtr->projectors.begin();
while (piter != this->dataPtr->projectors.end())
{
// Check to see if the projector is a child of the visual that is
// being removed.
if (piter->second->GetParent()->GetRootVisual()->GetName() ==
vis->GetRootVisual()->GetName())
{
delete piter->second;
this->dataPtr->projectors.erase(piter++);
}
else
++piter;
}
this->RemoveVisualizations(vis);
vis->Fini();
this->dataPtr->visuals.erase(iter);
if (this->dataPtr->selectedVis && this->dataPtr->selectedVis->GetId() ==
vis->GetId())
this->dataPtr->selectedVis.reset();
}
}
/////////////////////////////////////////////////
void Scene::RemoveVisual(VisualPtr _vis)
{
this->RemoveVisual(_vis->GetId());
}
/////////////////////////////////////////////////
void Scene::SetVisualId(VisualPtr _vis, uint32_t _id)
{
if (!_vis)
return;
auto iter = this->dataPtr->visuals.find(_vis->GetId());
if (iter != this->dataPtr->visuals.end())
{
this->dataPtr->visuals.erase(_vis->GetId());
this->dataPtr->visuals[_id] = _vis;
_vis->SetId(_id);
}
}
/////////////////////////////////////////////////
void Scene::AddLight(LightPtr _light)
{
std::string n = this->StripSceneName(_light->Name());
const auto iter = this->dataPtr->lights.find(n);
if (iter != this->dataPtr->lights.end())
gzerr << "Duplicate lights detected[" << _light->Name() << "]\n";
this->dataPtr->lights[n] = _light;
}
/////////////////////////////////////////////////
void Scene::RemoveLight(LightPtr _light)
{
if (_light)
{
// Delete the light
std::string n = this->StripSceneName(_light->Name());
this->dataPtr->lights.erase(n);
}
}
/////////////////////////////////////////////////
void Scene::SetGrid(const bool _enabled)
{
if (_enabled && this->dataPtr->grids.empty())
{
Grid *grid = new Grid(this, 20, 1, 10, common::Color(0.3, 0.3, 0.3, 0.5));
grid->Init();
this->dataPtr->grids.push_back(grid);
grid = new Grid(this, 4, 5, 20, common::Color(0.8, 0.8, 0.8, 0.5));
grid->Init();
this->dataPtr->grids.push_back(grid);
}
else
{
for (uint32_t i = 0; i < this->dataPtr->grids.size(); ++i)
{
this->dataPtr->grids[i]->Enable(_enabled);
}
}
}
/////////////////////////////////////////////////
void Scene::ShowOrigin(const bool _show)
{
this->dataPtr->originVisual->SetVisible(_show);
}
//////////////////////////////////////////////////
std::string Scene::StripSceneName(const std::string &_name) const
{
if (_name.find(this->Name() + "::") != std::string::npos)
return _name.substr(this->Name().size() + 2);
else
return _name;
}
//////////////////////////////////////////////////
Heightmap *Scene::GetHeightmap() const
{
std::lock_guard<std::mutex> lock(*this->dataPtr->receiveMutex);
return this->dataPtr->terrain;
}
/////////////////////////////////////////////////
void Scene::SetHeightmapLOD(const unsigned int _value)
{
this->dataPtr->heightmapLOD = _value;
if (this->dataPtr->terrain)
this->dataPtr->terrain->SetLOD(this->dataPtr->heightmapLOD);
}
/////////////////////////////////////////////////
unsigned int Scene::HeightmapLOD() const
{
if (this->dataPtr->terrain)
return this->dataPtr->terrain->LOD();
return this->dataPtr->heightmapLOD;
}
/////////////////////////////////////////////////
void Scene::SetHeightmapSkirtLength(const double _value)
{
this->dataPtr->heightmapSkirtLength = _value;
if (this->dataPtr->terrain)
this->dataPtr->terrain->SetSkirtLength(this->dataPtr->heightmapSkirtLength);
}
/////////////////////////////////////////////////
double Scene::HeightmapSkirtLength() const
{
if (this->dataPtr->terrain)
return this->dataPtr->terrain->SkirtLength();
return this->dataPtr->heightmapSkirtLength;
}
/////////////////////////////////////////////////
void Scene::CreateCOMVisual(ConstLinkPtr &_msg, VisualPtr _linkVisual)
{
COMVisualPtr comVis(new COMVisual(_linkVisual->GetName() + "_COM_VISUAL__",
_linkVisual));
comVis->Load(_msg);
comVis->SetVisible(this->dataPtr->showCOMs);
this->dataPtr->visuals[comVis->GetId()] = comVis;
}
/////////////////////////////////////////////////
void Scene::CreateCOMVisual(sdf::ElementPtr _elem, VisualPtr _linkVisual)
{
COMVisualPtr comVis(new COMVisual(_linkVisual->GetName() + "_COM_VISUAL__",
_linkVisual));
comVis->Load(_elem);
comVis->SetVisible(false);
this->dataPtr->visuals[comVis->GetId()] = comVis;
}
/////////////////////////////////////////////////
void Scene::CreateInertiaVisual(ConstLinkPtr &_msg, VisualPtr _linkVisual)
{
InertiaVisualPtr inertiaVis(new InertiaVisual(_linkVisual->GetName() +
"_INERTIA_VISUAL__", _linkVisual));
inertiaVis->Load(_msg);
inertiaVis->SetVisible(this->dataPtr->showInertias);
this->dataPtr->visuals[inertiaVis->GetId()] = inertiaVis;
}
/////////////////////////////////////////////////
void Scene::CreateInertiaVisual(sdf::ElementPtr _elem, VisualPtr _linkVisual)
{
InertiaVisualPtr inertiaVis(new InertiaVisual(_linkVisual->GetName() +
"_INERTIA_VISUAL__", _linkVisual));
inertiaVis->Load(_elem);
inertiaVis->SetVisible(false);
this->dataPtr->visuals[inertiaVis->GetId()] = inertiaVis;
}
/////////////////////////////////////////////////
void Scene::CreateLinkFrameVisual(ConstLinkPtr &/*_msg*/, VisualPtr _linkVisual)
{
LinkFrameVisualPtr linkFrameVis(new LinkFrameVisual(_linkVisual->GetName() +
"_LINK_FRAME_VISUAL__", _linkVisual));
linkFrameVis->Load();
linkFrameVis->SetVisible(this->dataPtr->showLinkFrames);
this->dataPtr->visuals[linkFrameVis->GetId()] = linkFrameVis;
}
/////////////////////////////////////////////////
void Scene::RemoveVisualizations(rendering::VisualPtr _vis)
{
std::vector<VisualPtr> toRemove;
for (unsigned int i = 0; i < _vis->GetChildCount(); ++i)
{
rendering::VisualPtr childVis = _vis->GetChild(i);
Visual::VisualType visType = childVis->GetType();
if (visType == Visual::VT_PHYSICS || visType == Visual::VT_SENSOR
|| visType == Visual::VT_GUI)
{
// do not remove ModelManipulator's SelectionObj
// FIXME remove this hardcoded check, issue #1832
if (std::dynamic_pointer_cast<SelectionObj>(childVis) != NULL)
continue;
toRemove.push_back(childVis);
}
}
for (auto vis : toRemove)
this->RemoveVisual(vis);
}
/////////////////////////////////////////////////
void Scene::SetWireframe(const bool _show)
{
this->dataPtr->wireframe = _show;
for (auto visual : this->dataPtr->visuals)
{
visual.second->SetWireframe(_show);
}
if (this->dataPtr->terrain)
this->dataPtr->terrain->SetWireframe(_show);
}
/////////////////////////////////////////////////
bool Scene::Wireframe() const
{
return this->dataPtr->wireframe;
}
/////////////////////////////////////////////////
void Scene::SetTransparent(const bool _show)
{
this->dataPtr->transparent = _show;
for (auto visual : this->dataPtr->visuals)
{
if (visual.second->GetType() == Visual::VT_MODEL)
visual.second->SetTransparency(_show ? 0.5 : 0.0);
}
}
/////////////////////////////////////////////////
void Scene::ShowCOMs(const bool _show)
{
this->dataPtr->showCOMs = _show;
for (auto visual : this->dataPtr->visuals)
{
visual.second->ShowCOM(_show);
}
}
/////////////////////////////////////////////////
void Scene::ShowInertias(const bool _show)
{
this->dataPtr->showInertias = _show;
for (auto visual : this->dataPtr->visuals)
{
visual.second->ShowInertia(_show);
}
}
/////////////////////////////////////////////////
void Scene::ShowLinkFrames(const bool _show)
{
this->dataPtr->showLinkFrames = _show;
for (auto visual : this->dataPtr->visuals)
{
visual.second->ShowLinkFrame(_show);
}
}
/////////////////////////////////////////////////
void Scene::ShowCollisions(const bool _show)
{
this->dataPtr->showCollisions = _show;
for (auto visual : this->dataPtr->visuals)
{
visual.second->ShowCollision(_show);
}
}
/////////////////////////////////////////////////
void Scene::ShowJoints(const bool _show)
{
this->dataPtr->showJoints = _show;
for (auto visual : this->dataPtr->visuals)
{
visual.second->ShowJoints(_show);
}
}
/////////////////////////////////////////////////
void Scene::ShowContacts(const bool _show)
{
ContactVisualPtr vis;
if (this->dataPtr->contactVisId == GZ_UINT32_MAX && _show)
{
vis.reset(new ContactVisual("__GUIONLY_CONTACT_VISUAL__",
this->dataPtr->worldVisual, "~/physics/contacts"));
vis->SetEnabled(_show);
this->dataPtr->contactVisId = vis->GetId();
this->dataPtr->visuals[this->dataPtr->contactVisId] = vis;
}
else
vis = std::dynamic_pointer_cast<ContactVisual>(
this->dataPtr->visuals[this->dataPtr->contactVisId]);
if (vis)
vis->SetEnabled(_show);
else
gzerr << "Unable to get contact visualization. This should never happen.\n";
}
/////////////////////////////////////////////////
void Scene::ShowClouds(const bool _show)
{
if (!this->dataPtr->skyx)
return;
SkyX::VCloudsManager *mgr = this->dataPtr->skyx->getVCloudsManager();
if (mgr)
{
SkyX::VClouds::VClouds *vclouds =
this->dataPtr->skyx->getVCloudsManager()->getVClouds();
if (vclouds)
vclouds->setVisible(_show);
}
}
/////////////////////////////////////////////////
bool Scene::GetShowClouds() const
{
return this->ShowClouds();
}
/////////////////////////////////////////////////
bool Scene::ShowClouds() const
{
if (!this->dataPtr->skyx)
return false;
SkyX::VCloudsManager *mgr = this->dataPtr->skyx->getVCloudsManager();
if (mgr)
{
SkyX::VClouds::VClouds *vclouds =
this->dataPtr->skyx->getVCloudsManager()->getVClouds();
if (vclouds)
return vclouds->isVisible();
}
return false;
}
/////////////////////////////////////////////////
void Scene::SetSkyXMode(const unsigned int _mode)
{
/// \todo This function is currently called on initialization of rendering
/// based sensors to disable clouds and moon. More testing is required to
/// make sure it functions correctly when called during a render update,
/// issue #693.
if (!this->dataPtr->skyx)
return;
bool enabled = _mode != GZ_SKYX_NONE;
this->dataPtr->skyx->setEnabled(enabled);
if (!enabled)
return;
this->dataPtr->skyx->setCloudsEnabled(_mode & GZ_SKYX_CLOUDS);
this->dataPtr->skyx->setMoonEnabled(_mode & GZ_SKYX_MOON);
}
/////////////////////////////////////////////////
SkyX::SkyX *Scene::GetSkyX() const
{
return this->dataPtr->skyx;
}
/////////////////////////////////////////////////
void Scene::RemoveProjectors()
{
for (std::map<std::string, Projector *>::iterator iter =
this->dataPtr->projectors.begin();
iter != this->dataPtr->projectors.end(); ++iter)
{
delete iter->second;
}
this->dataPtr->projectors.clear();
}
/////////////////////////////////////////////////
void Scene::ToggleLayer(const int32_t _layer)
{
for (auto visual : this->dataPtr->visuals)
{
visual.second->ToggleLayer(_layer);
}
}
/////////////////////////////////////////////////
void Scene::EnableVisualizations(const bool _enable)
{
this->dataPtr->enableVisualizations = _enable;
}
/////////////////////////////////////////////////
bool Scene::EnableVisualizations() const
{
return this->dataPtr->enableVisualizations;
}