$search
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 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 // 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 ogre_tools 00289 00290