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