00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "selection_manager.h"
00031 #include "properties/property.h"
00032 #include "properties/property_manager.h"
00033 #include "visualization_manager.h"
00034 #include "render_panel.h"
00035 #include "view_controller.h"
00036 #include "common.h"
00037
00038 #include <ogre_tools/shape.h>
00039 #include <ogre_tools/axes.h>
00040 #include <ogre_tools/arrow.h>
00041 #include <ogre_tools/wx_ogre_render_window.h>
00042
00043 #include <ros/assert.h>
00044
00045 #include <OGRE/OgreCamera.h>
00046 #include <OGRE/OgreViewport.h>
00047 #include <OGRE/OgreRenderTexture.h>
00048 #include <OGRE/OgreTextureManager.h>
00049 #include <OGRE/OgreSceneNode.h>
00050 #include <OGRE/OgreSceneManager.h>
00051 #include <OGRE/OgreManualObject.h>
00052 #include <OGRE/OgreWireBoundingBox.h>
00053 #include <OGRE/OgreRoot.h>
00054 #include <OGRE/OgreHardwarePixelBuffer.h>
00055 #include <OGRE/OgreMaterialManager.h>
00056 #include <OGRE/OgreEntity.h>
00057 #include <OGRE/OgreSubEntity.h>
00058
00059 #include <boost/scoped_array.hpp>
00060
00061 #include <algorithm>
00062
00063 namespace rviz
00064 {
00065
00066 SelectionHandler::SelectionHandler()
00067 : manager_(0)
00068 , listener_(new Listener(this))
00069 {
00070
00071 }
00072
00073 SelectionHandler::~SelectionHandler()
00074 {
00075 S_Movable::iterator it = tracked_objects_.begin();
00076 S_Movable::iterator end = tracked_objects_.end();
00077 for (; it != end; ++it)
00078 {
00079 Ogre::MovableObject* m = *it;
00080 m->setListener(0);
00081 }
00082
00083 while (!boxes_.empty())
00084 {
00085 destroyBox(boxes_.begin()->first);
00086 }
00087 }
00088
00089 void SelectionHandler::initialize(VisualizationManager* manager)
00090 {
00091 manager_ = manager;
00092 }
00093
00094 void SelectionHandler::preRenderPass(uint32_t pass)
00095 {
00096 M_HandleToBox::iterator it = boxes_.begin();
00097 M_HandleToBox::iterator end = boxes_.end();
00098 for (; it != end; ++it)
00099 {
00100 Ogre::WireBoundingBox* box = it->second.second;
00101 box->setVisible(false);
00102 }
00103 }
00104
00105 void SelectionHandler::postRenderPass(uint32_t pass)
00106 {
00107 M_HandleToBox::iterator it = boxes_.begin();
00108 M_HandleToBox::iterator end = boxes_.end();
00109 for (; it != end; ++it)
00110 {
00111 Ogre::WireBoundingBox* box = it->second.second;
00112 box->setVisible(true);
00113 }
00114 }
00115
00116 void SelectionHandler::addTrackedObject(Ogre::MovableObject* object)
00117 {
00118 tracked_objects_.insert(object);
00119 object->setListener(listener_.get());
00120 }
00121
00122 void SelectionHandler::removeTrackedObject(Ogre::MovableObject* object)
00123 {
00124 tracked_objects_.erase(object);
00125 object->setListener(0);
00126
00127 updateTrackedBoxes();
00128 }
00129
00130 void SelectionHandler::updateTrackedBoxes()
00131 {
00132 M_HandleToBox::iterator it = boxes_.begin();
00133 M_HandleToBox::iterator end = boxes_.end();
00134 for (; it != end; ++it)
00135 {
00136 V_AABB aabbs;
00137 Picked p(it->first.first);
00138 p.extra_handles.insert(it->first.second);
00139 getAABBs(Picked(it->first.first), aabbs);
00140
00141 if (!aabbs.empty())
00142 {
00143 Ogre::AxisAlignedBox combined;
00144 V_AABB::iterator aabb_it = aabbs.begin();
00145 V_AABB::iterator aabb_end = aabbs.end();
00146 for (; aabb_it != aabb_end; ++aabb_it)
00147 {
00148 combined.merge(*aabb_it);
00149 }
00150
00151 createBox(std::make_pair(p.handle, it->first.second), combined, "RVIZ/Cyan");
00152 }
00153 }
00154 }
00155
00156 void SelectionHandler::getAABBs(const Picked& obj, V_AABB& aabbs)
00157 {
00158 S_Movable::iterator it = tracked_objects_.begin();
00159 S_Movable::iterator end = tracked_objects_.end();
00160 for (; it != end; ++it)
00161 {
00162 aabbs.push_back((*it)->getWorldBoundingBox());
00163 }
00164 }
00165
00166 void SelectionHandler::updateProperties()
00167 {
00168 V_Property::iterator it = properties_.begin();
00169 V_Property::iterator end = properties_.end();
00170 for (; it != end; ++it)
00171 {
00172 propertyChanged(*it);
00173 }
00174 }
00175
00176 void SelectionHandler::destroyProperties(const Picked& obj, PropertyManager* property_manager)
00177 {
00178 V_Property::iterator it = properties_.begin();
00179 V_Property::iterator end = properties_.end();
00180 for (; it != end; ++it)
00181 {
00182 property_manager->deleteProperty((*it).lock());
00183 }
00184 }
00185
00186 void SelectionHandler::createBox(const std::pair<CollObjectHandle, uint64_t>& handles, const Ogre::AxisAlignedBox& aabb, const std::string& material_name)
00187 {
00188 Ogre::WireBoundingBox* box = 0;
00189 Ogre::SceneNode* node = 0;
00190
00191 M_HandleToBox::iterator it = boxes_.find(handles);
00192 if (it == boxes_.end())
00193 {
00194 Ogre::SceneManager* scene_manager = manager_->getSceneManager();
00195 node = scene_manager->getRootSceneNode()->createChildSceneNode();
00196 box = new Ogre::WireBoundingBox;
00197
00198 bool inserted = boxes_.insert(std::make_pair(handles, std::make_pair(node, box))).second;
00199 ROS_ASSERT(inserted);
00200 }
00201 else
00202 {
00203 node = it->second.first;
00204 box = it->second.second;
00205 }
00206
00207 box->setMaterial(material_name);
00208
00209 box->setupBoundingBox(aabb);
00210 node->detachAllObjects();
00211 node->attachObject(box);
00212 }
00213
00214 void SelectionHandler::destroyBox(const std::pair<CollObjectHandle, uint64_t>& handles)
00215 {
00216 M_HandleToBox::iterator it = boxes_.find(handles);
00217 if (it != boxes_.end())
00218 {
00219 Ogre::SceneNode* node = it->second.first;
00220 Ogre::WireBoundingBox* box = it->second.second;
00221
00222 node->detachAllObjects();
00223 node->getParentSceneNode()->removeAndDestroyChild(node->getName());
00224
00225 delete box;
00226
00227 boxes_.erase(it);
00228 }
00229 }
00230
00231 void SelectionHandler::onSelect(const Picked& obj)
00232 {
00233 ROS_DEBUG("Selected 0x%08x", obj.handle);
00234
00235 V_AABB aabbs;
00236 getAABBs(obj, aabbs);
00237
00238 if (!aabbs.empty())
00239 {
00240 Ogre::AxisAlignedBox combined;
00241 V_AABB::iterator it = aabbs.begin();
00242 V_AABB::iterator end = aabbs.end();
00243 for (; it != end; ++it)
00244 {
00245 combined.merge(*it);
00246 }
00247
00248 createBox(std::make_pair(obj.handle, 0ULL), combined, "RVIZ/Cyan");
00249 }
00250 }
00251
00252 void SelectionHandler::onDeselect(const Picked& obj)
00253 {
00254 ROS_DEBUG("Deselected 0x%08x", obj.handle);
00255
00256 destroyBox(std::make_pair(obj.handle, 0ULL));
00257 }
00258
00259 SelectionManager::SelectionManager(VisualizationManager* manager)
00260 : vis_manager_(manager)
00261 , highlight_enabled_(false)
00262 , uid_counter_(0)
00263 {
00264 for (uint32_t i = 0; i < s_num_render_textures_; ++i)
00265 {
00266 pixel_boxes_[i].data = 0;
00267 }
00268 }
00269
00270 SelectionManager::~SelectionManager()
00271 {
00272 setSelection(M_Picked());
00273
00274 clearHandlers();
00275
00276 highlight_node_->getParentSceneNode()->removeAndDestroyChild(highlight_node_->getName());
00277 delete highlight_rectangle_;
00278
00279 for (uint32_t i = 0; i < s_num_render_textures_; ++i)
00280 {
00281 delete [] (uint8_t*)pixel_boxes_[i].data;
00282 }
00283 }
00284
00285 void SelectionManager::initialize()
00286 {
00287
00288 for (uint32_t i = 0; i < s_num_render_textures_; ++i)
00289 {
00290 std::stringstream ss;
00291 static int count = 0;
00292 ss << "SelectionTexture" << count++;
00293
00294 render_textures_[i] = Ogre::TextureManager::getSingleton().createManual(ss.str(), Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D, s_render_texture_size_, s_render_texture_size_, 0, Ogre::PF_R8G8B8, Ogre::TU_STATIC | Ogre::TU_RENDERTARGET);
00295 Ogre::RenderTexture* render_texture = render_textures_[i]->getBuffer()->getRenderTarget();
00296 render_texture->setAutoUpdated(false);
00297
00298 #if defined(PICKING_DEBUG)
00299 Ogre::Rectangle2D* mini_screen = new Ogre::Rectangle2D(true);
00300 mini_screen->setCorners(0.0, i, 1.0, -1.0 + (i));
00301 Ogre::AxisAlignedBox aabInf;
00302 aabInf.setInfinite();
00303 mini_screen->setBoundingBox(aabInf);
00304 Ogre::SceneNode* mini_screen_node = vis_manager_->getSceneManager()->getRootSceneNode()->createChildSceneNode(ss.str() + "MiniScreenNode");
00305 mini_screen_node->attachObject(mini_screen);
00306 debug_nodes_[i] = mini_screen_node;
00307
00308 Ogre::MaterialPtr material = Ogre::MaterialManager::getSingleton().create(ss.str() + "RttMat", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
00309 Ogre::Technique *technique = material->createTechnique();
00310 technique->createPass();
00311 material->getTechnique(0)->getPass(0)->setLightingEnabled(false);
00312 material->getTechnique(0)->getPass(0)->createTextureUnitState(render_textures_[i]->getName());
00313
00314 mini_screen->setMaterial(material->getName());
00315 #endif
00316 }
00317
00318
00319 Ogre::SceneManager* scene_manager = vis_manager_->getSceneManager();
00320 highlight_node_ = scene_manager->getRootSceneNode()->createChildSceneNode();
00321
00322 std::stringstream ss;
00323 static int count = 0;
00324 ss << "SelectionRect" << count++;
00325 highlight_rectangle_ = new Ogre::Rectangle2D(true);
00326
00327 const static uint32_t texture_data[1] = { 0xffff0080 };
00328 Ogre::DataStreamPtr pixel_stream;
00329 pixel_stream.bind(new Ogre::MemoryDataStream( (void*)&texture_data[0], 4 ));
00330
00331 Ogre::TexturePtr tex = Ogre::TextureManager::getSingleton().loadRawData(ss.str() + "Texture", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, pixel_stream, 1, 1, Ogre::PF_R8G8B8A8, Ogre::TEX_TYPE_2D, 0);
00332
00333 Ogre::MaterialPtr material = Ogre::MaterialManager::getSingleton().create(ss.str(), Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
00334 material->setLightingEnabled(false);
00335
00336 highlight_rectangle_->setMaterial(material->getName());
00337 Ogre::AxisAlignedBox aabInf;
00338 aabInf.setInfinite();
00339 highlight_rectangle_->setBoundingBox(aabInf);
00340 highlight_rectangle_->setRenderQueueGroup(Ogre::RENDER_QUEUE_OVERLAY - 1);
00341 material->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA);
00342 material->setCullingMode(Ogre::CULL_NONE);
00343
00344 Ogre::TextureUnitState* tex_unit = material->getTechnique(0)->getPass(0)->createTextureUnitState();
00345 tex_unit->setTextureName(tex->getName());
00346 tex_unit->setTextureFiltering( Ogre::TFO_NONE );
00347
00348 highlight_node_->attachObject(highlight_rectangle_);
00349 }
00350
00351 void SelectionManager::clearHandlers()
00352 {
00353 boost::recursive_mutex::scoped_lock lock(global_mutex_);
00354
00355 objects_.clear();
00356 }
00357
00358 void SelectionManager::addObject(CollObjectHandle obj, const SelectionHandlerPtr& handler)
00359 {
00360 if (!obj)
00361 {
00362
00363 return;
00364 }
00365
00366 boost::recursive_mutex::scoped_lock lock(global_mutex_);
00367
00368 handler->initialize(vis_manager_);
00369
00370 bool inserted = objects_.insert(std::make_pair(obj, handler)).second;
00371 ROS_ASSERT(inserted);
00372 }
00373
00374 void SelectionManager::removeObject(CollObjectHandle obj)
00375 {
00376 if (!obj)
00377 {
00378 return;
00379 }
00380
00381 boost::recursive_mutex::scoped_lock lock(global_mutex_);
00382
00383 M_Picked::iterator it = selection_.find(obj);
00384 if (it != selection_.end())
00385 {
00386 M_Picked objs;
00387 objs.insert(std::make_pair(it->first, it->second));
00388
00389 removeSelection(objs);
00390 }
00391
00392 objects_.erase(obj);
00393 }
00394
00395 void SelectionManager::update()
00396 {
00397 boost::recursive_mutex::scoped_lock lock(global_mutex_);
00398
00399 highlight_node_->setVisible(highlight_enabled_);
00400
00401 if (highlight_enabled_)
00402 {
00403 setHighlightRect(highlight_.viewport, highlight_.x1, highlight_.y1, highlight_.x2, highlight_.y2);
00404
00405 #if 0
00406 M_Picked results;
00407 highlight_node_->setVisible(false);
00408 pick(highlight_.viewport, highlight_.x1, highlight_.y1, highlight_.x2, highlight_.y2, results);
00409 highlight_node_->setVisible(true);
00410 #endif
00411 }
00412 }
00413
00414 void SelectionManager::highlight(Ogre::Viewport* viewport, int x1, int y1, int x2, int y2)
00415 {
00416 boost::recursive_mutex::scoped_lock lock(global_mutex_);
00417
00418 highlight_enabled_ = true;
00419
00420 highlight_.viewport = viewport;
00421 highlight_.x1 = x1;
00422 highlight_.y1 = y1;
00423 highlight_.x2 = x2;
00424 highlight_.y2 = y2;
00425 }
00426
00427 void SelectionManager::removeHighlight()
00428 {
00429 boost::recursive_mutex::scoped_lock lock(global_mutex_);
00430
00431 highlight_enabled_ = false;
00432 }
00433
00434 void SelectionManager::select(Ogre::Viewport* viewport, int x1, int y1, int x2, int y2, SelectType type)
00435 {
00436 boost::recursive_mutex::scoped_lock lock(global_mutex_);
00437
00438 vis_manager_->lockRender();
00439
00440 highlight_enabled_ = false;
00441 highlight_node_->setVisible(false);
00442
00443 M_Picked results;
00444 pick(viewport, x1, y1, x2, y2, results);
00445
00446 if (type == Add)
00447 {
00448 addSelection(results);
00449 }
00450 else if (type == Remove)
00451 {
00452 removeSelection(results);
00453 }
00454 else if (type == Replace)
00455 {
00456 setSelection(results);
00457 }
00458
00459 vis_manager_->unlockRender();
00460 }
00461
00462 void SelectionManager::setHighlightRect(Ogre::Viewport* viewport, int x1, int y1, int x2, int y2)
00463 {
00464 float nx1 = ((float)x1 / viewport->getActualWidth()) * 2 - 1;
00465 float nx2 = ((float)x2 / viewport->getActualWidth()) * 2 - 1;
00466 float ny1 = -(((float)y1 / viewport->getActualHeight()) * 2 - 1);
00467 float ny2 = -(((float)y2 / viewport->getActualHeight()) * 2 - 1);
00468
00469 nx1 = nx1 < -1 ? -1 : (nx1 > 1 ? 1 : nx1);
00470 ny1 = ny1 < -1 ? -1 : (ny1 > 1 ? 1 : ny1);
00471 nx2 = nx2 < -1 ? -1 : (nx2 > 1 ? 1 : nx2);
00472 ny2 = ny2 < -1 ? -1 : (ny2 > 1 ? 1 : ny2);
00473
00474 highlight_rectangle_->setCorners(nx1, ny1, nx2, ny2);
00475 }
00476
00477 void SelectionManager::unpackColors(Ogre::Viewport* pick_viewport, Ogre::Viewport* render_viewport, const Ogre::PixelBox& box, int x1, int y1, int x2, int y2, V_Pixel& pixels)
00478 {
00479 float width = pick_viewport->getActualWidth();
00480 float height = pick_viewport->getActualHeight();
00481 int render_width = render_viewport->getActualWidth();
00482 int render_height = render_viewport->getActualHeight();
00483
00484
00485
00486 float fracw = render_width / width;
00487 float frach = render_height / height;
00488 x1 = x1 * fracw;
00489 x2 = x2 * fracw;
00490 y1 = y1 * frach;
00491 y2 = y2 * frach;
00492
00493 x1 = x1 < 0 ? 0 : (x1 > render_width ? render_width : x1);
00494 y1 = y1 < 0 ? 0 : (y1 > render_height ? render_height : y1);
00495 x2 = x2 < 0 ? 0 : (x2 > render_width ? render_width : x2);
00496 y2 = y2 < 0 ? 0 : (y2 > render_height ? render_height : y2);
00497
00498 int step_x = (x2 - x1) >= 0 ? 1 : -1;
00499 int step_y = (y2 - y1) >= 0 ? 1 : -1;
00500 pixels.resize((abs(x2 - x1) + 1) * (abs(y2 - y1) + 1));
00501 int i = 0;
00502 for (int y = y1; y != (y2 + step_y); y += step_y)
00503 {
00504 for (int x = x1; x != (x2 + step_x); x += step_x)
00505 {
00506 uint32_t pos = (x + y*render_width) * 4;
00507
00508 uint32_t pix_val = *(uint32_t*)((uint8_t*)box.data + pos);
00509 uint32_t handle = colorToHandle(box.format, pix_val);
00510
00511 Pixel& p = pixels[i];
00512 p.x = x;
00513 p.y = y;
00514 p.handle = handle;
00515
00516 ++i;
00517 }
00518 }
00519 }
00520
00521 void SelectionManager::renderAndUnpack(Ogre::Viewport* viewport, uint32_t pass, int x1, int y1, int x2, int y2, V_Pixel& pixels)
00522 {
00523 ROS_ASSERT(pass < s_num_render_textures_);
00524
00525 Ogre::TexturePtr tex = render_textures_[pass];
00526 Ogre::HardwarePixelBufferSharedPtr pixel_buffer = tex->getBuffer();
00527 Ogre::RenderTexture* render_texture = pixel_buffer->getRenderTarget();
00528
00529 if (render_texture->getNumViewports() == 0 || render_texture->getViewport(0)->getCamera() != viewport->getCamera())
00530 {
00531 render_texture->removeAllViewports();
00532 render_texture->addViewport(viewport->getCamera());
00533 Ogre::Viewport* render_viewport = render_texture->getViewport(0);
00534 render_viewport->setClearEveryFrame(true);
00535 render_viewport->setBackgroundColour(Ogre::ColourValue::Black);
00536 render_viewport->setOverlaysEnabled(false);
00537
00538 std::stringstream scheme;
00539 scheme << "Pick";
00540 if (pass > 0)
00541 {
00542 scheme << pass;
00543 }
00544
00545 render_viewport->setMaterialScheme(scheme.str());
00546 }
00547
00548 render_texture->update();
00549
00550 Ogre::Viewport* render_viewport = pixel_buffer->getRenderTarget()->getViewport(0);
00551 int render_width = render_viewport->getActualWidth();
00552 int render_height = render_viewport->getActualHeight();
00553
00554 Ogre::PixelFormat format = pixel_buffer->getFormat();
00555
00556 int size = Ogre::PixelUtil::getMemorySize(render_width, render_height, 1, format);
00557 uint8_t* data = new uint8_t[size];
00558
00559 Ogre::PixelBox& box = pixel_boxes_[pass];
00560 delete [] (uint8_t*)box.data;
00561 box = Ogre::PixelBox(render_width, render_height, 1, format, data);
00562
00563 pixel_buffer->blitToMemory(box);
00564
00565 unpackColors(viewport, render_viewport, box, x1, y1, x2, y2, pixels);
00566 }
00567
00568 void SelectionManager::pick(Ogre::Viewport* viewport, int x1, int y1, int x2, int y2, M_Picked& results)
00569 {
00570 boost::recursive_mutex::scoped_lock lock(global_mutex_);
00571
00572 #if defined(PICKING_DEBUG)
00573 for (int i = 0; i < s_num_render_textures_; ++i)
00574 {
00575 debug_nodes_[i]->setVisible(false);
00576 }
00577 #endif
00578
00579 bool need_additional_render = false;
00580
00581 V_CollObject handles_by_pixel;
00582 S_CollObject need_additional;
00583
00584 V_Pixel& pixels = pixel_buffer_;
00585
00586
00587
00588 {
00589 M_CollisionObjectToSelectionHandler::iterator handler_it = objects_.begin();
00590 M_CollisionObjectToSelectionHandler::iterator handler_end = objects_.end();
00591 for (; handler_it != handler_end; ++handler_it)
00592 {
00593 const SelectionHandlerPtr& handler = handler_it->second;
00594
00595 handler->preRenderPass(0);
00596 }
00597
00598 renderAndUnpack(viewport, 0, x1, y1, x2, y2, pixels);
00599
00600 handler_it = objects_.begin();
00601 handler_end = objects_.end();
00602 for (; handler_it != handler_end; ++handler_it)
00603 {
00604 const SelectionHandlerPtr& handler = handler_it->second;
00605
00606 handler->postRenderPass(0);
00607 }
00608
00609 handles_by_pixel.reserve(pixels.size());
00610 V_Pixel::iterator it = pixels.begin();
00611 V_Pixel::iterator end = pixels.end();
00612 for (; it != end; ++it)
00613 {
00614 const Pixel& p = *it;
00615
00616 CollObjectHandle handle = p.handle;
00617
00618 handles_by_pixel.push_back(handle);
00619
00620 if (handle == 0)
00621 {
00622 continue;
00623 }
00624
00625 SelectionHandlerPtr handler = getHandler(handle);
00626 if (handle && handler)
00627 {
00628 if (results.insert(std::make_pair(handle, Picked(handle))).second)
00629 {
00630 if (handler->needsAdditionalRenderPass(1))
00631 {
00632 need_additional.insert(handle);
00633 need_additional_render = true;
00634 }
00635 }
00636 }
00637 }
00638 }
00639
00640 uint32_t pass = 1;
00641
00642 V_uint64 extra_by_pixel;
00643 extra_by_pixel.resize(handles_by_pixel.size());
00644 while (need_additional_render && pass < s_num_render_textures_)
00645 {
00646 {
00647 S_CollObject::iterator need_it = need_additional.begin();
00648 S_CollObject::iterator need_end = need_additional.end();
00649 for (; need_it != need_end; ++need_it)
00650 {
00651 SelectionHandlerPtr handler = getHandler(*need_it);
00652 ROS_ASSERT(handler);
00653
00654 handler->preRenderPass(pass);
00655 }
00656 }
00657
00658 renderAndUnpack(viewport, pass, x1, y1, x2, y2, pixels);
00659
00660 {
00661 S_CollObject::iterator need_it = need_additional.begin();
00662 S_CollObject::iterator need_end = need_additional.end();
00663 for (; need_it != need_end; ++need_it)
00664 {
00665 SelectionHandlerPtr handler = getHandler(*need_it);
00666 ROS_ASSERT(handler);
00667
00668 handler->postRenderPass(pass);
00669 }
00670 }
00671
00672 int i = 0;
00673 V_Pixel::iterator pix_it = pixels.begin();
00674 V_Pixel::iterator pix_end = pixels.end();
00675 for (; pix_it != pix_end; ++pix_it, ++i)
00676 {
00677 const Pixel& p = *pix_it;
00678
00679 CollObjectHandle handle = handles_by_pixel[i];
00680
00681 if (pass == 1)
00682 {
00683 extra_by_pixel[i] = 0;
00684 }
00685
00686 if (need_additional.find(handle) != need_additional.end())
00687 {
00688 CollObjectHandle extra_handle = p.handle;
00689 extra_by_pixel[i] |= extra_handle << (32 * (pass-1));
00690 }
00691 else
00692 {
00693 extra_by_pixel[i] = 0;
00694 }
00695 }
00696
00697 need_additional_render = false;
00698 need_additional.clear();
00699 M_Picked::iterator handle_it = results.begin();
00700 M_Picked::iterator handle_end = results.end();
00701 for (; handle_it != handle_end; ++handle_it)
00702 {
00703 CollObjectHandle handle = handle_it->first;
00704
00705 if (getHandler(handle)->needsAdditionalRenderPass(pass + 1))
00706 {
00707 need_additional_render = true;
00708 need_additional.insert(handle);
00709 }
00710 }
00711 }
00712
00713 int i = 0;
00714 V_uint64::iterator pix_2_it = extra_by_pixel.begin();
00715 V_uint64::iterator pix_2_end = extra_by_pixel.end();
00716 for (; pix_2_it != pix_2_end; ++pix_2_it, ++i)
00717 {
00718 CollObjectHandle handle = handles_by_pixel[i];
00719
00720 if (handle == 0)
00721 {
00722 continue;
00723 }
00724
00725 M_Picked::iterator picked_it = results.find(handle);
00726 if (picked_it == results.end())
00727 {
00728 continue;
00729 }
00730
00731 Picked& picked = picked_it->second;
00732
00733 if (*pix_2_it)
00734 {
00735 picked.extra_handles.insert(*pix_2_it);
00736 }
00737 }
00738
00739
00740 viewport->getCamera()->_notifyViewport(viewport);
00741
00742 #if defined(PICKING_DEBUG)
00743 for (int i = 0; i < s_num_render_textures_; ++i)
00744 {
00745 debug_nodes_[i]->setVisible(true);
00746 }
00747 #endif
00748 }
00749
00750 void SelectionManager::addPickTechnique(CollObjectHandle handle, const Ogre::MaterialPtr& material)
00751 {
00752 Ogre::DataStreamPtr pixel_stream;
00753 pixel_stream.bind(new Ogre::MemoryDataStream( &handle, 3 ));
00754
00755 Ogre::Technique* technique = 0;
00756
00757 uint32_t num_techs = material->getNumTechniques();
00758 for (uint32_t i = 0; i < num_techs; ++i)
00759 {
00760 Ogre::Technique* tech = material->getTechnique(i);
00761
00762 if (tech->getSchemeName() == "Pick")
00763 {
00764 technique = tech;
00765 break;
00766 }
00767 }
00768
00769 if (!technique)
00770 {
00771 technique = material->createTechnique();
00772 technique->setSchemeName("Pick");
00773 Ogre::Pass* pass = technique->createPass();
00774 pass->setLightingEnabled(false);
00775 pass->setSceneBlending(Ogre::SBT_REPLACE);
00776
00777 Ogre::TexturePtr tex = Ogre::TextureManager::getSingleton().loadRawData(material->getName() + "PickTexture", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, pixel_stream, 1, 1, Ogre::PF_R8G8B8, Ogre::TEX_TYPE_2D, 0);
00778 Ogre::TextureUnitState* tex_unit = pass->createTextureUnitState();
00779 tex_unit->setTextureName(tex->getName());
00780 tex_unit->setTextureFiltering( Ogre::TFO_NONE );
00781 tex_unit->setColourOperation(Ogre::LBO_REPLACE);
00782 }
00783 else
00784 {
00785 Ogre::TextureUnitState* tex_unit = technique->getPass(0)->getTextureUnitState(0);
00786 std::string tex_name = tex_unit->getTextureName();
00787
00788 Ogre::TexturePtr tex = Ogre::TextureManager::getSingleton().getByName(tex_name);
00789 tex->unload();
00790 tex->loadRawData(pixel_stream, 1, 1, Ogre::PF_R8G8B8);
00791 }
00792 }
00793
00794 CollObjectHandle SelectionManager::createCollisionForObject(ogre_tools::Object* obj, const SelectionHandlerPtr& handler, CollObjectHandle coll)
00795 {
00796 boost::recursive_mutex::scoped_lock lock(global_mutex_);
00797
00798 bool use_original = false;
00799
00800 if (coll)
00801 {
00802 use_original = true;
00803 }
00804 else
00805 {
00806 coll = createHandle();
00807 }
00808
00809 if (ogre_tools::Shape* shape = dynamic_cast<ogre_tools::Shape*>(obj))
00810 {
00811 createCollisionForEntity(shape->getEntity(), handler, coll);
00812 if (!use_original)
00813 {
00814 handler->addTrackedObject(shape->getEntity());
00815 }
00816 }
00817 else if (ogre_tools::Axes* axes = dynamic_cast<ogre_tools::Axes*>(obj))
00818 {
00819 createCollisionForEntity(axes->getXShape()->getEntity(), handler, coll);
00820 createCollisionForEntity(axes->getYShape()->getEntity(), handler, coll);
00821 createCollisionForEntity(axes->getZShape()->getEntity(), handler, coll);
00822
00823 if (!use_original)
00824 {
00825 handler->addTrackedObject(axes->getXShape()->getEntity());
00826 handler->addTrackedObject(axes->getYShape()->getEntity());
00827 handler->addTrackedObject(axes->getZShape()->getEntity());
00828 }
00829 }
00830 else if (ogre_tools::Arrow* arrow = dynamic_cast<ogre_tools::Arrow*>(obj))
00831 {
00832 createCollisionForEntity(arrow->getHead()->getEntity(), handler, coll);
00833 createCollisionForEntity(arrow->getShaft()->getEntity(), handler, coll);
00834
00835 if (!use_original)
00836 {
00837 handler->addTrackedObject(arrow->getHead()->getEntity());
00838 handler->addTrackedObject(arrow->getShaft()->getEntity());
00839 }
00840 }
00841
00842 if (coll)
00843 {
00844 if (!use_original)
00845 {
00846 addObject(coll, handler);
00847 }
00848 }
00849
00850 return coll;
00851 }
00852
00853 CollObjectHandle SelectionManager::createCollisionForEntity(Ogre::Entity* entity, const SelectionHandlerPtr& handler, CollObjectHandle coll)
00854 {
00855 boost::recursive_mutex::scoped_lock lock(global_mutex_);
00856
00857 bool use_original = false;
00858
00859 if (coll)
00860 {
00861 use_original = true;
00862 }
00863 else
00864 {
00865 coll = createHandle();
00866 }
00867
00868 typedef std::set<Ogre::Material*> M_Material;
00869 M_Material materials;
00870
00871 uint32_t num_sub_entities = entity->getNumSubEntities();
00872 for (uint32_t i = 0; i < num_sub_entities; ++i)
00873 {
00874 Ogre::SubEntity* sub = entity->getSubEntity(i);
00875
00876 Ogre::MaterialPtr material = sub->getMaterial();
00877
00878 if (materials.insert(material.get()).second)
00879 {
00880 addPickTechnique(coll, material);
00881 }
00882 }
00883
00884 if (!use_original)
00885 {
00886 handler->addTrackedObject(entity);
00887 addObject(coll, handler);
00888 }
00889
00890 return coll;
00891 }
00892
00893 SelectionHandlerPtr SelectionManager::getHandler(CollObjectHandle obj)
00894 {
00895 boost::recursive_mutex::scoped_lock lock(global_mutex_);
00896
00897 M_CollisionObjectToSelectionHandler::iterator it = objects_.find(obj);
00898 if (it != objects_.end())
00899 {
00900 return it->second;
00901 }
00902
00903 return SelectionHandlerPtr();
00904 }
00905
00906 void SelectionManager::removeSelection(const M_Picked& objs)
00907 {
00908 boost::recursive_mutex::scoped_lock lock(global_mutex_);
00909
00910 M_Picked::const_iterator it = objs.begin();
00911 M_Picked::const_iterator end = objs.end();
00912 for (; it != end; ++it)
00913 {
00914 removeSelection(it->second);
00915 }
00916
00917 selection_removed_(SelectionRemovedArgs(objs));
00918 }
00919
00920 void SelectionManager::addSelection(const M_Picked& objs)
00921 {
00922 boost::recursive_mutex::scoped_lock lock(global_mutex_);
00923
00924 M_Picked added;
00925 M_Picked::const_iterator it = objs.begin();
00926 M_Picked::const_iterator end = objs.end();
00927 for (; it != end; ++it)
00928 {
00929 std::pair<Picked, bool> ppb = addSelection(it->second);
00930 if (ppb.second)
00931 {
00932 added.insert(std::make_pair(it->first, ppb.first));
00933 }
00934 }
00935
00936 selection_added_(SelectionAddedArgs(added));
00937 }
00938
00939 void SelectionManager::setSelection(const M_Picked& objs)
00940 {
00941 boost::recursive_mutex::scoped_lock lock(global_mutex_);
00942
00943 selection_setting_(SelectionSettingArgs());
00944
00945 M_Picked original(selection_.begin(), selection_.end());
00946
00947 removeSelection(original);
00948 addSelection(objs);
00949
00950 selection_set_(SelectionSetArgs(original, selection_));
00951 }
00952
00953 std::pair<Picked, bool> SelectionManager::addSelection(const Picked& obj)
00954 {
00955 boost::recursive_mutex::scoped_lock lock(global_mutex_);
00956
00957 std::pair<M_Picked::iterator, bool> pib = selection_.insert(std::make_pair(obj.handle, obj));
00958
00959 SelectionHandlerPtr handler = getHandler(obj.handle);
00960
00961 if (pib.second)
00962 {
00963 handler->onSelect(obj);
00964 return std::make_pair(obj, true);
00965 }
00966 else
00967 {
00968 Picked& cur = pib.first->second;
00969 Picked added(cur.handle);
00970
00971 S_uint64::iterator it = obj.extra_handles.begin();
00972 S_uint64::iterator end = obj.extra_handles.end();
00973 for (; it != end; ++it)
00974 {
00975 if (cur.extra_handles.insert(*it).second)
00976 {
00977 added.extra_handles.insert(*it);
00978 }
00979 }
00980
00981 if (!added.extra_handles.empty())
00982 {
00983 handler->onSelect(added);
00984
00985 return std::make_pair(added, true);
00986 }
00987 }
00988
00989 return std::make_pair(Picked(0), false);
00990 }
00991
00992 void SelectionManager::removeSelection(const Picked& obj)
00993 {
00994 boost::recursive_mutex::scoped_lock lock(global_mutex_);
00995
00996 M_Picked::iterator sel_it = selection_.find(obj.handle);
00997 if (sel_it != selection_.end())
00998 {
00999 S_uint64::iterator extra_it = obj.extra_handles.begin();
01000 S_uint64::iterator extra_end = obj.extra_handles.end();
01001 for (; extra_it != extra_end; ++extra_it)
01002 {
01003 sel_it->second.extra_handles.erase(*extra_it);
01004 }
01005
01006 if (sel_it->second.extra_handles.empty())
01007 {
01008 selection_.erase(sel_it);
01009 }
01010 }
01011
01012 SelectionHandlerPtr handler = getHandler(obj.handle);
01013 handler->onDeselect(obj);
01014 }
01015
01016 void SelectionManager::focusOnSelection()
01017 {
01018 boost::recursive_mutex::scoped_lock lock(global_mutex_);
01019
01020 if (selection_.empty())
01021 {
01022 return;
01023 }
01024
01025 Ogre::AxisAlignedBox combined;
01026
01027 M_Picked::iterator it = selection_.begin();
01028 M_Picked::iterator end = selection_.end();
01029 for (; it != end; ++it)
01030 {
01031 const Picked& p = it->second;
01032
01033 SelectionHandlerPtr handler = getHandler(p.handle);
01034
01035 V_AABB aabbs;
01036 handler->getAABBs(p, aabbs);
01037
01038 V_AABB::iterator aabb_it = aabbs.begin();
01039 V_AABB::iterator aabb_end = aabbs.end();
01040 for (; aabb_it != aabb_end; ++aabb_it)
01041 {
01042 combined.merge(*aabb_it);
01043 }
01044 }
01045
01046 if (!combined.isInfinite() && !combined.isNull())
01047 {
01048 Ogre::Vector3 center = combined.getCenter();
01049 ViewController* controller = vis_manager_->getCurrentViewController();
01050 controller->lookAt(center);
01051 }
01052 }
01053
01054 }