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 <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 ogre_tools
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
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
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 }
00289
00290