Go to the documentation of this file.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 "billboard_line.h"
00031
00032 #include <OgreSceneManager.h>
00033 #include <OgreSceneNode.h>
00034 #include <OgreVector3.h>
00035 #include <OgreQuaternion.h>
00036 #include <OgreBillboardChain.h>
00037 #include <OgreMaterialManager.h>
00038 #include <OgreTechnique.h>
00039
00040 #include <sstream>
00041
00042 #include <ros/assert.h>
00043
00044 #define MAX_ELEMENTS (65536/4)
00045
00046 namespace rviz
00047 {
00048
00049 BillboardLine::BillboardLine( Ogre::SceneManager* scene_manager, Ogre::SceneNode* parent_node )
00050 : Object( scene_manager )
00051 , width_( 0.1f )
00052 , current_line_(0)
00053 , total_elements_(0)
00054 , num_lines_(1)
00055 , max_points_per_line_(100)
00056 , lines_per_chain_(0)
00057 , current_chain_(0)
00058 , elements_in_current_chain_(0)
00059 {
00060 if ( !parent_node )
00061 {
00062 parent_node = scene_manager_->getRootSceneNode();
00063 }
00064
00065 scene_node_ = parent_node->createChildSceneNode();
00066
00067 static int count = 0;
00068 std::stringstream ss;
00069 ss << "BillboardLineMaterial" << count++;
00070 material_ = Ogre::MaterialManager::getSingleton().create( ss.str(), Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME );
00071 material_->setReceiveShadows(false);
00072 material_->getTechnique(0)->setLightingEnabled(false);
00073
00074 setNumLines(num_lines_);
00075 setMaxPointsPerLine(max_points_per_line_);
00076 }
00077
00078 BillboardLine::~BillboardLine()
00079 {
00080 V_Chain::iterator it = chains_.begin();
00081 V_Chain::iterator end = chains_.end();
00082 for (;it != end; ++it)
00083 {
00084 scene_manager_->destroyBillboardChain(*it);
00085 }
00086
00087 scene_manager_->destroySceneNode( scene_node_->getName() );
00088
00089 Ogre::MaterialManager::getSingleton().remove(material_->getName());
00090 }
00091
00092 Ogre::BillboardChain* BillboardLine::createChain()
00093 {
00094 std::stringstream ss;
00095 static int count = 0;
00096 ss << "BillboardLine chain" << count++;
00097 Ogre::BillboardChain* chain = scene_manager_->createBillboardChain(ss.str());
00098 chain->setMaterialName( material_->getName() );
00099 scene_node_->attachObject( chain );
00100
00101 chains_.push_back(chain);
00102
00103 return chain;
00104 }
00105
00106 void BillboardLine::clear()
00107 {
00108 V_Chain::iterator it = chains_.begin();
00109 V_Chain::iterator end = chains_.end();
00110 for (; it != end; ++it)
00111 {
00112 (*it)->clearAllChains();
00113 }
00114
00115 current_line_ = 0;
00116 total_elements_ = 0;
00117 current_chain_ = 0;
00118 elements_in_current_chain_ = 0;
00119
00120 for (V_uint32::iterator it = num_elements_.begin(); it != num_elements_.end(); ++it)
00121 {
00122 *it = 0;
00123 }
00124 }
00125
00126 void BillboardLine::setupChains()
00127 {
00128 uint32_t total_points = max_points_per_line_ * num_lines_;
00129 uint32_t num_chains = total_points / MAX_ELEMENTS;
00130 if (total_points % MAX_ELEMENTS != 0)
00131 {
00132 ++num_chains;
00133 }
00134
00135 for (uint32_t i = chains_.size(); i < num_chains; ++i)
00136 {
00137 createChain();
00138 }
00139
00140 lines_per_chain_ = MAX_ELEMENTS / max_points_per_line_;
00141
00142 V_Chain::iterator it = chains_.begin();
00143 V_Chain::iterator end = chains_.end();
00144 for (;it != end; ++it)
00145 {
00146 (*it)->setMaxChainElements(max_points_per_line_);
00147
00148
00149 if (it + 1 == end)
00150 {
00151 uint32_t lines_left = num_lines_ % lines_per_chain_;
00152 (*it)->setNumberOfChains(lines_left);
00153 }
00154 else
00155 {
00156 (*it)->setNumberOfChains(lines_per_chain_);
00157 }
00158 }
00159 }
00160
00161 void BillboardLine::setMaxPointsPerLine(uint32_t max)
00162 {
00163 max_points_per_line_ = max;
00164
00165 setupChains();
00166 }
00167
00168 void BillboardLine::setNumLines(uint32_t num)
00169 {
00170 num_lines_ = num;
00171
00172 setupChains();
00173
00174 num_elements_.resize(num);
00175
00176 for (V_uint32::iterator it = num_elements_.begin(); it != num_elements_.end(); ++it)
00177 {
00178 *it = 0;
00179 }
00180 }
00181
00182 void BillboardLine::newLine()
00183 {
00184 ++current_line_;
00185
00186 ROS_ASSERT(current_line_ < num_lines_);
00187 }
00188
00189 void BillboardLine::addPoint( const Ogre::Vector3& point )
00190 {
00191 addPoint(point, color_);
00192 }
00193
00194 void BillboardLine::addPoint( const Ogre::Vector3& point, const Ogre::ColourValue& color )
00195 {
00196 ++num_elements_[current_line_];
00197 ++total_elements_;
00198
00199 ROS_ASSERT(num_elements_[current_line_] <= max_points_per_line_);
00200
00201 ++elements_in_current_chain_;
00202 if (elements_in_current_chain_ > MAX_ELEMENTS)
00203 {
00204 ++current_chain_;
00205 elements_in_current_chain_ = 1;
00206 }
00207
00208 Ogre::BillboardChain::Element e;
00209 e.position = point;
00210 e.width = width_;
00211 e.colour = color;
00212 chains_[current_chain_]->addChainElement(current_line_ % lines_per_chain_ , e);
00213 }
00214
00215 void BillboardLine::setLineWidth( float width )
00216 {
00217 width_ = width;
00218
00219 for (uint32_t line = 0; line < num_lines_; ++line)
00220 {
00221 uint32_t element_count = num_elements_[line];
00222
00223 for ( uint32_t i = 0; i < element_count; ++i )
00224 {
00225 Ogre::BillboardChain* c = chains_[line / lines_per_chain_];
00226 Ogre::BillboardChain::Element e = c->getChainElement(line % lines_per_chain_, i);
00227
00228 e.width = width_;
00229 c->updateChainElement(line % lines_per_chain_, i, e);
00230 }
00231 }
00232 }
00233
00234 void BillboardLine::setPosition( const Ogre::Vector3& position )
00235 {
00236 scene_node_->setPosition( position );
00237 }
00238
00239 void BillboardLine::setOrientation( const Ogre::Quaternion& orientation )
00240 {
00241 scene_node_->setOrientation( orientation );
00242 }
00243
00244 void BillboardLine::setScale( const Ogre::Vector3& scale )
00245 {
00246
00247 }
00248
00249 void BillboardLine::setColor( float r, float g, float b, float a )
00250 {
00251 if ( a < 0.9998 )
00252 {
00253 material_->getTechnique(0)->setSceneBlending( Ogre::SBT_TRANSPARENT_ALPHA );
00254 material_->getTechnique(0)->setDepthWriteEnabled( false );
00255 }
00256 else
00257 {
00258 material_->getTechnique(0)->setSceneBlending( Ogre::SBT_REPLACE );
00259 material_->getTechnique(0)->setDepthWriteEnabled( true );
00260 }
00261
00262 color_ = Ogre::ColourValue( r, g, b, a );
00263
00264 for (uint32_t line = 0; line < num_lines_; ++line)
00265 {
00266 uint32_t element_count = num_elements_[line];
00267
00268 for ( uint32_t i = 0; i < element_count; ++i )
00269 {
00270 Ogre::BillboardChain* c = chains_[line / lines_per_chain_];
00271 Ogre::BillboardChain::Element e = c->getChainElement(line % lines_per_chain_, i);
00272
00273 e.colour = color_;
00274 c->updateChainElement(line % lines_per_chain_, i, e);
00275 }
00276 }
00277 }
00278
00279 const Ogre::Vector3& BillboardLine::getPosition()
00280 {
00281 return scene_node_->getPosition();
00282 }
00283
00284 const Ogre::Quaternion& BillboardLine::getOrientation()
00285 {
00286 return scene_node_->getOrientation();
00287 }
00288
00289 }
00290
00291