billboard_line.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2008, Willow Garage, Inc.
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  *     * Redistributions of source code must retain the above copyright
00009  *       notice, this list of conditions and the following disclaimer.
00010  *     * Redistributions in binary form must reproduce the above copyright
00011  *       notice, this list of conditions and the following disclaimer in the
00012  *       documentation and/or other materials provided with the distribution.
00013  *     * Neither the name of the Willow Garage, Inc. nor the names of its
00014  *       contributors may be used to endorse or promote products derived from
00015  *       this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027  * POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 
00030 #include "billboard_line.h"
00031 
00032 #include <OGRE/OgreSceneManager.h>
00033 #include <OGRE/OgreSceneNode.h>
00034 #include <OGRE/OgreVector3.h>
00035 #include <OGRE/OgreQuaternion.h>
00036 #include <OGRE/OgreBillboardChain.h>
00037 #include <OGRE/OgreMaterialManager.h>
00038 
00039 #include <sstream>
00040 
00041 #include <ros/assert.h>
00042 
00043 #define MAX_ELEMENTS (65536/4)
00044 
00045 namespace rviz
00046 {
00047 
00048 BillboardLine::BillboardLine( Ogre::SceneManager* scene_manager, Ogre::SceneNode* parent_node )
00049 : Object( scene_manager )
00050 , width_( 0.1f )
00051 , current_line_(0)
00052 , total_elements_(0)
00053 , num_lines_(1)
00054 , max_points_per_line_(100)
00055 , lines_per_chain_(0)
00056 , current_chain_(0)
00057 , elements_in_current_chain_(0)
00058 {
00059   if ( !parent_node )
00060   {
00061     parent_node = scene_manager_->getRootSceneNode();
00062   }
00063 
00064   scene_node_ = parent_node->createChildSceneNode();
00065 
00066   static int count = 0;
00067   std::stringstream ss;
00068   ss << "BillboardLineMaterial" << count++;
00069   material_ = Ogre::MaterialManager::getSingleton().create( ss.str(), Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME );
00070   material_->setReceiveShadows(false);
00071   material_->getTechnique(0)->setLightingEnabled(false);
00072 
00073   setNumLines(num_lines_);
00074   setMaxPointsPerLine(max_points_per_line_);
00075 }
00076 
00077 BillboardLine::~BillboardLine()
00078 {
00079   V_Chain::iterator it = chains_.begin();
00080   V_Chain::iterator end = chains_.end();
00081   for (;it != end; ++it)
00082   {
00083     scene_manager_->destroyBillboardChain(*it);
00084   }
00085 
00086   scene_manager_->destroySceneNode( scene_node_->getName() );
00087 
00088   material_->unload();
00089 }
00090 
00091 Ogre::BillboardChain* BillboardLine::createChain()
00092 {
00093   std::stringstream ss;
00094   static int count = 0;
00095   ss << "BillboardLine chain" << count++;
00096   Ogre::BillboardChain* chain = scene_manager_->createBillboardChain(ss.str());
00097   chain->setMaterialName( material_->getName() );
00098   scene_node_->attachObject( chain );
00099 
00100   chains_.push_back(chain);
00101 
00102   return chain;
00103 }
00104 
00105 void BillboardLine::clear()
00106 {
00107   V_Chain::iterator it = chains_.begin();
00108   V_Chain::iterator end = chains_.end();
00109   for (; it != end; ++it)
00110   {
00111     (*it)->clearAllChains();
00112   }
00113 
00114   current_line_ = 0;
00115   total_elements_ = 0;
00116   current_chain_ = 0;
00117   elements_in_current_chain_ = 0;
00118 
00119   for (V_uint32::iterator it = num_elements_.begin(); it != num_elements_.end(); ++it)
00120   {
00121     *it = 0;
00122   }
00123 }
00124 
00125 void BillboardLine::setupChains()
00126 {
00127   uint32_t total_points = max_points_per_line_ * num_lines_;
00128   uint32_t num_chains = total_points / MAX_ELEMENTS;
00129   if (total_points % MAX_ELEMENTS != 0)
00130   {
00131     ++num_chains;
00132   }
00133 
00134   for (uint32_t i = chains_.size(); i < num_chains; ++i)
00135   {
00136     createChain();
00137   }
00138 
00139   lines_per_chain_ = MAX_ELEMENTS / max_points_per_line_;
00140 
00141   V_Chain::iterator it = chains_.begin();
00142   V_Chain::iterator end = chains_.end();
00143   for (;it != end; ++it)
00144   {
00145     (*it)->setMaxChainElements(max_points_per_line_);
00146 
00147     // shorten the number of chains in the last bbchain, to avoid memory wasteage
00148     if (it + 1 == end)
00149     {
00150       uint32_t lines_left = num_lines_ % lines_per_chain_;
00151       (*it)->setNumberOfChains(lines_left);
00152     }
00153     else
00154     {
00155       (*it)->setNumberOfChains(lines_per_chain_);
00156     }
00157   }
00158 }
00159 
00160 void BillboardLine::setMaxPointsPerLine(uint32_t max)
00161 {
00162   max_points_per_line_ = max;
00163 
00164   setupChains();
00165 }
00166 
00167 void BillboardLine::setNumLines(uint32_t num)
00168 {
00169   num_lines_ = num;
00170 
00171   setupChains();
00172 
00173   num_elements_.resize(num);
00174 
00175   for (V_uint32::iterator it = num_elements_.begin(); it != num_elements_.end(); ++it)
00176   {
00177     *it = 0;
00178   }
00179 }
00180 
00181 void BillboardLine::newLine()
00182 {
00183   ++current_line_;
00184 
00185   ROS_ASSERT(current_line_ < num_lines_);
00186 }
00187 
00188 void BillboardLine::addPoint( const Ogre::Vector3& point )
00189 {
00190   addPoint(point, color_);
00191 }
00192 
00193 void BillboardLine::addPoint( const Ogre::Vector3& point, const Ogre::ColourValue& color )
00194 {
00195   ++num_elements_[current_line_];
00196   ++total_elements_;
00197 
00198   ROS_ASSERT(num_elements_[current_line_] <= max_points_per_line_);
00199 
00200   ++elements_in_current_chain_;
00201   if (elements_in_current_chain_ > MAX_ELEMENTS)
00202   {
00203     ++current_chain_;
00204     elements_in_current_chain_ = 1;
00205   }
00206 
00207   Ogre::BillboardChain::Element e;
00208   e.position = point;
00209   e.width = width_;
00210   e.colour = color;
00211   chains_[current_chain_]->addChainElement(current_line_ % lines_per_chain_ , e);
00212 }
00213 
00214 void BillboardLine::setLineWidth( float width )
00215 {
00216   width_ = width;
00217 
00218   for (uint32_t line = 0; line < num_lines_; ++line)
00219   {
00220     uint32_t element_count = num_elements_[line];
00221 
00222     for ( uint32_t i = 0; i < element_count; ++i )
00223     {
00224       Ogre::BillboardChain* c = chains_[line / lines_per_chain_];
00225       Ogre::BillboardChain::Element e = c->getChainElement(line % lines_per_chain_, i);
00226 
00227       e.width = width_;
00228       c->updateChainElement(line % lines_per_chain_, i, e);
00229     }
00230   }
00231 }
00232 
00233 void BillboardLine::setPosition( const Ogre::Vector3& position )
00234 {
00235   scene_node_->setPosition( position );
00236 }
00237 
00238 void BillboardLine::setOrientation( const Ogre::Quaternion& orientation )
00239 {
00240   scene_node_->setOrientation( orientation );
00241 }
00242 
00243 void BillboardLine::setScale( const Ogre::Vector3& scale )
00244 {
00245   // Setting scale doesn't really make sense here
00246 }
00247 
00248 void BillboardLine::setColor( float r, float g, float b, float a )
00249 {
00250   if ( a < 0.9998 )
00251   {
00252     material_->getTechnique(0)->setSceneBlending( Ogre::SBT_TRANSPARENT_ALPHA );
00253     material_->getTechnique(0)->setDepthWriteEnabled( false );
00254   }
00255   else
00256   {
00257     material_->getTechnique(0)->setSceneBlending( Ogre::SBT_REPLACE );
00258     material_->getTechnique(0)->setDepthWriteEnabled( true );
00259   }
00260 
00261   color_ = Ogre::ColourValue( r, g, b, a );
00262 
00263   for (uint32_t line = 0; line < num_lines_; ++line)
00264   {
00265     uint32_t element_count = num_elements_[line];
00266 
00267     for ( uint32_t i = 0; i < element_count; ++i )
00268     {
00269       Ogre::BillboardChain* c = chains_[line / lines_per_chain_];
00270       Ogre::BillboardChain::Element e = c->getChainElement(line % lines_per_chain_, i);
00271 
00272       e.colour = color_;
00273       c->updateChainElement(line % lines_per_chain_, i, e);
00274     }
00275   }
00276 }
00277 
00278 const Ogre::Vector3& BillboardLine::getPosition()
00279 {
00280   return scene_node_->getPosition();
00281 }
00282 
00283 const Ogre::Quaternion& BillboardLine::getOrientation()
00284 {
00285   return scene_node_->getOrientation();
00286 }
00287 
00288 } // namespace rviz
00289 
00290 


rviz
Author(s): Dave Hershberger, Josh Faust
autogenerated on Mon Jan 6 2014 11:54:32